diff options
author | Petr Mrázek <peterix@gmail.com> | 2017-09-16 23:09:05 +0200 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2017-09-17 19:24:39 +0200 |
commit | 9a6c2b0e2c0a4fb9f26b9c9d1137a66d7977251b (patch) | |
tree | 962cbb167d58cc022ceb4d7bbc4e3b4e00a5849f /api/logic/minecraft/legacy/LegacyModList.cpp | |
parent | b2b04876009400c04658d9b986b86d3edeb3b51a (diff) | |
download | MultiMC-9a6c2b0e2c0a4fb9f26b9c9d1137a66d7977251b.tar MultiMC-9a6c2b0e2c0a4fb9f26b9c9d1137a66d7977251b.tar.gz MultiMC-9a6c2b0e2c0a4fb9f26b9c9d1137a66d7977251b.tar.lz MultiMC-9a6c2b0e2c0a4fb9f26b9c9d1137a66d7977251b.tar.xz MultiMC-9a6c2b0e2c0a4fb9f26b9c9d1137a66d7977251b.zip |
NOISSUE Add back Legacy for migration purposes
Diffstat (limited to 'api/logic/minecraft/legacy/LegacyModList.cpp')
-rw-r--r-- | api/logic/minecraft/legacy/LegacyModList.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/api/logic/minecraft/legacy/LegacyModList.cpp b/api/logic/minecraft/legacy/LegacyModList.cpp new file mode 100644 index 00000000..061752e0 --- /dev/null +++ b/api/logic/minecraft/legacy/LegacyModList.cpp @@ -0,0 +1,171 @@ +/* Copyright 2013-2017 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LegacyModList.h" +#include <FileSystem.h> +#include <QString> +#include <QDebug> + +LegacyModList::LegacyModList(const QString &dir, const QString &list_file) + : m_dir(dir), m_list_file(list_file) +{ + FS::ensureFolderPathExists(m_dir.absolutePath()); + m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs | + QDir::NoSymLinks); + m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware); +} + + struct OrderItem + { + QString id; + bool enabled = false; + }; + typedef QList<OrderItem> OrderList; + +static void internalSort(QList<Mod> &what) +{ + auto predicate = [](const Mod &left, const Mod &right) + { + if (left.name() == right.name()) + { + return left.mmc_id().localeAwareCompare(right.mmc_id()) < 0; + } + return left.name().localeAwareCompare(right.name()) < 0; + }; + std::sort(what.begin(), what.end(), predicate); +} + +static OrderList readListFile(const QString &m_list_file) +{ + OrderList itemList; + if (m_list_file.isNull() || m_list_file.isEmpty()) + return itemList; + + QFile textFile(m_list_file); + if (!textFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return OrderList(); + + QTextStream textStream; + textStream.setAutoDetectUnicode(true); + textStream.setDevice(&textFile); + while (true) + { + QString line = textStream.readLine(); + if (line.isNull() || line.isEmpty()) + break; + else + { + OrderItem it; + it.enabled = !line.endsWith(".disabled"); + if (!it.enabled) + { + line.chop(9); + } + it.id = line; + itemList.append(it); + } + } + textFile.close(); + return itemList; +} + +bool LegacyModList::update() +{ + if (!m_dir.exists() || !m_dir.isReadable()) + return false; + + QList<Mod> orderedMods; + QList<Mod> newMods; + m_dir.refresh(); + auto folderContents = m_dir.entryInfoList(); + bool orderOrStateChanged = false; + + // first, process the ordered items (if any) + OrderList listOrder = readListFile(m_list_file); + for (auto item : listOrder) + { + QFileInfo infoEnabled(m_dir.filePath(item.id)); + QFileInfo infoDisabled(m_dir.filePath(item.id + ".disabled")); + int idxEnabled = folderContents.indexOf(infoEnabled); + int idxDisabled = folderContents.indexOf(infoDisabled); + bool isEnabled; + // if both enabled and disabled versions are present, it's a special case... + if (idxEnabled >= 0 && idxDisabled >= 0) + { + // we only process the one we actually have in the order file. + // and exactly as we have it. + // THIS IS A CORNER CASE + isEnabled = item.enabled; + } + else + { + // only one is present. + // we pick the one that we found. + // we assume the mod was enabled/disabled by external means + isEnabled = idxEnabled >= 0; + } + int idx = isEnabled ? idxEnabled : idxDisabled; + QFileInfo &info = isEnabled ? infoEnabled : infoDisabled; + // if the file from the index file exists + if (idx != -1) + { + // remove from the actual folder contents list + folderContents.takeAt(idx); + // append the new mod + orderedMods.append(Mod(info)); + if (isEnabled != item.enabled) + orderOrStateChanged = true; + } + else + { + orderOrStateChanged = true; + } + } + // if there are any untracked files... + if (folderContents.size()) + { + // the order surely changed! + for (auto entry : folderContents) + { + newMods.append(Mod(entry)); + } + internalSort(newMods); + orderedMods.append(newMods); + orderOrStateChanged = true; + } + // otherwise, if we were already tracking some mods + else if (mods.size()) + { + // if the number doesn't match, order changed. + if (mods.size() != orderedMods.size()) + orderOrStateChanged = true; + // if it does match, compare the mods themselves + else + for (int i = 0; i < mods.size(); i++) + { + if (!mods[i].strongCompare(orderedMods[i])) + { + orderOrStateChanged = true; + break; + } + } + } + mods.swap(orderedMods); + if (orderOrStateChanged && !m_list_file.isEmpty()) + { + qDebug() << "Mod list " << m_list_file << " changed!"; + } + return true; +} |