diff options
Diffstat (limited to 'launcher/minecraft/legacy/LegacyModList.cpp')
-rw-r--r-- | launcher/minecraft/legacy/LegacyModList.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/launcher/minecraft/legacy/LegacyModList.cpp b/launcher/minecraft/legacy/LegacyModList.cpp new file mode 100644 index 00000000..7301eb8c --- /dev/null +++ b/launcher/minecraft/legacy/LegacyModList.cpp @@ -0,0 +1,136 @@ +/* Copyright 2013-2021 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<LegacyModList::Mod> &what) +{ + auto predicate = [](const LegacyModList::Mod &left, const LegacyModList::Mod &right) + { + return left.fileName().localeAwareCompare(right.fileName()) < 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(); + + // 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(info); + } + } + // if there are any untracked files... append them sorted at the end + if (folderContents.size()) + { + for (auto entry : folderContents) + { + newMods.append(entry); + } + internalSort(newMods); + orderedMods.append(newMods); + } + mods.swap(orderedMods); + return true; +} |