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 | |
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')
-rw-r--r-- | api/logic/CMakeLists.txt | 4 | ||||
-rw-r--r-- | api/logic/Env.cpp | 2 | ||||
-rw-r--r-- | api/logic/Env.h | 1 | ||||
-rw-r--r-- | api/logic/FolderInstanceProvider.cpp | 5 | ||||
-rw-r--r-- | api/logic/minecraft/ModList.h | 1 | ||||
-rw-r--r-- | api/logic/minecraft/legacy/LegacyInstance.cpp | 313 | ||||
-rw-r--r-- | api/logic/minecraft/legacy/LegacyInstance.h | 128 | ||||
-rw-r--r-- | api/logic/minecraft/legacy/LegacyModList.cpp | 171 | ||||
-rw-r--r-- | api/logic/minecraft/legacy/LegacyModList.h | 56 |
9 files changed, 678 insertions, 3 deletions
diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index 909e51a9..5cd80166 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -228,6 +228,10 @@ set(MINECRAFT_SOURCES minecraft/launch/LauncherPartLaunch.h minecraft/launch/PrintInstanceInfo.cpp minecraft/launch/PrintInstanceInfo.h + minecraft/legacy/LegacyModList.h + minecraft/legacy/LegacyModList.cpp + minecraft/legacy/LegacyInstance.h + minecraft/legacy/LegacyInstance.cpp minecraft/GradleSpecifier.h minecraft/MinecraftInstance.cpp minecraft/MinecraftInstance.h diff --git a/api/logic/Env.cpp b/api/logic/Env.cpp index e2abda49..cf321af2 100644 --- a/api/logic/Env.cpp +++ b/api/logic/Env.cpp @@ -19,8 +19,6 @@ struct Env::Private shared_qobject_ptr<HttpMetaCache> m_metacache; std::shared_ptr<IIconList> m_iconlist; shared_qobject_ptr<Meta::Index> m_metadataIndex; - // FIXME: replace with mojang format LWJGL in meta store - std::shared_ptr<LWJGLVersionList> m_lwjgllist; QString m_jarsPath; }; diff --git a/api/logic/Env.h b/api/logic/Env.h index 3dadc58e..276d762d 100644 --- a/api/logic/Env.h +++ b/api/logic/Env.h @@ -13,7 +13,6 @@ class QNetworkAccessManager; class HttpMetaCache; class BaseVersionList; class BaseVersion; -class LWJGLVersionList; namespace Meta { diff --git a/api/logic/FolderInstanceProvider.cpp b/api/logic/FolderInstanceProvider.cpp index a0fbd46a..25e9bb84 100644 --- a/api/logic/FolderInstanceProvider.cpp +++ b/api/logic/FolderInstanceProvider.cpp @@ -2,6 +2,7 @@ #include "settings/INISettingsObject.h" #include "FileSystem.h" #include "minecraft/MinecraftInstance.h" +#include "minecraft/legacy/LegacyInstance.h" #include "NullInstance.h" #include <QDir> @@ -90,6 +91,10 @@ InstancePtr FolderInstanceProvider::loadInstance(const InstanceId& id) { inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot)); } + else if (inst_type == "Legacy") + { + inst.reset(new LegacyInstance(m_globalSettings, instanceSettings, instanceRoot)); + } else { inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot)); diff --git a/api/logic/minecraft/ModList.h b/api/logic/minecraft/ModList.h index f9b6b1c5..8cdd2d9a 100644 --- a/api/logic/minecraft/ModList.h +++ b/api/logic/minecraft/ModList.h @@ -24,6 +24,7 @@ #include "multimc_logic_export.h" +class LegacyInstance; class BaseInstance; class QFileSystemWatcher; diff --git a/api/logic/minecraft/legacy/LegacyInstance.cpp b/api/logic/minecraft/legacy/LegacyInstance.cpp new file mode 100644 index 00000000..532e8307 --- /dev/null +++ b/api/logic/minecraft/legacy/LegacyInstance.cpp @@ -0,0 +1,313 @@ +/* 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 <QFileInfo> +#include <minecraft/launch/LauncherPartLaunch.h> +#include <QDir> +#include <settings/Setting.h> + +#include "LegacyInstance.h" + +#include "minecraft/legacy/LegacyModList.h" +#include "minecraft/ModList.h" +#include "minecraft/WorldList.h" +#include <MMCZip.h> +#include <FileSystem.h> + +LegacyInstance::LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir) + : BaseInstance(globalSettings, settings, rootDir) +{ + settings->registerSetting("NeedsRebuild", true); + settings->registerSetting("ShouldUpdate", false); + settings->registerSetting("JarVersion", "Unknown"); + settings->registerSetting("IntendedJarVersion", ""); + /* + * custom base jar has no default. it is determined in code... see the accessor methods for + *it + * + * for instances that DO NOT have the CustomBaseJar setting (legacy instances), + * [.]minecraft/bin/mcbackup.jar is the default base jar + */ + settings->registerSetting("UseCustomBaseJar", true); + settings->registerSetting("CustomBaseJar", ""); +} + +QString LegacyInstance::baseJar() const +{ + bool customJar = m_settings->get("UseCustomBaseJar").toBool(); + if (customJar) + { + return customBaseJar(); + } + else + return defaultBaseJar(); +} + +QString LegacyInstance::customBaseJar() const +{ + QString value = m_settings->get("CustomBaseJar").toString(); + if (value.isNull() || value.isEmpty()) + { + return defaultCustomBaseJar(); + } + return value; +} + +bool LegacyInstance::shouldUseCustomBaseJar() const +{ + return m_settings->get("UseCustomBaseJar").toBool(); +} + + +shared_qobject_ptr<Task> LegacyInstance::createUpdateTask() +{ + return nullptr; +} + +/* +class LegacyJarModTask : public Task +{ + //Q_OBJECT +public: + explicit LegacyJarModTask(std::shared_ptr<LegacyInstance> inst) : Task(nullptr), m_inst(inst) + { + } + virtual void executeTask() + { + if (!m_inst->shouldRebuild()) + { + emitSucceeded(); + return; + } + + // Get the mod list + auto modList = m_inst->getJarMods(); + + QFileInfo runnableJar(m_inst->runnableJar()); + QFileInfo baseJar(m_inst->baseJar()); + bool base_is_custom = m_inst->shouldUseCustomBaseJar(); + + // Nothing to do if there are no jar mods to install, no backup and just the mc jar + if (base_is_custom) + { + // yes, this can happen if the instance only has the runnable jar and not the base jar + // it *could* be assumed that such an instance is vanilla, but that wouldn't be safe + // because that's not something mmc4 guarantees + if (runnableJar.isFile() && !baseJar.exists() && modList.empty()) + { + m_inst->setShouldRebuild(false); + emitSucceeded(); + return; + } + + setStatus(tr("Installing mods: Backing up minecraft.jar ...")); + if (!baseJar.exists() && !QFile::copy(runnableJar.filePath(), baseJar.filePath())) + { + emitFailed("It seems both the active and base jar are gone. A fresh base jar will " + "be used on next run."); + m_inst->setShouldRebuild(true); + m_inst->setShouldUpdate(true); + m_inst->setShouldUseCustomBaseJar(false); + return; + } + } + + if (!baseJar.exists()) + { + emitFailed("The base jar " + baseJar.filePath() + " does not exist"); + return; + } + + if (runnableJar.exists() && !QFile::remove(runnableJar.filePath())) + { + emitFailed("Failed to delete old minecraft.jar"); + return; + } + + setStatus(tr("Installing mods: Opening minecraft.jar ...")); + + QString outputJarPath = runnableJar.filePath(); + QString inputJarPath = baseJar.filePath(); + + if(!MMCZip::createModdedJar(inputJarPath, outputJarPath, modList)) + { + emitFailed(tr("Failed to create the custom Minecraft jar file.")); + return; + } + m_inst->setShouldRebuild(false); + // inst->UpdateVersion(true); + emitSucceeded(); + return; + + } + std::shared_ptr<LegacyInstance> m_inst; +}; +*/ + +std::shared_ptr<LegacyModList> LegacyInstance::jarModList() const +{ + if (!jar_mod_list) + { + auto list = new LegacyModList(jarModsDir(), modListFile()); + jar_mod_list.reset(list); + } + jar_mod_list->update(); + return jar_mod_list; +} + +QList<Mod> LegacyInstance::getJarMods() const +{ + return jarModList()->allMods(); +} + +QString LegacyInstance::minecraftRoot() const +{ + QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft")); + QFileInfo dotMCDir(FS::PathCombine(instanceRoot(), ".minecraft")); + + if (dotMCDir.exists() && !mcDir.exists()) + return dotMCDir.filePath(); + else + return mcDir.filePath(); +} + +QString LegacyInstance::binRoot() const +{ + return FS::PathCombine(minecraftRoot(), "bin"); +} + +QString LegacyInstance::jarModsDir() const +{ + return FS::PathCombine(instanceRoot(), "instMods"); +} + +QString LegacyInstance::libDir() const +{ + return FS::PathCombine(minecraftRoot(), "lib"); +} + +QString LegacyInstance::savesDir() const +{ + return FS::PathCombine(minecraftRoot(), "saves"); +} + +QString LegacyInstance::loaderModsDir() const +{ + return FS::PathCombine(minecraftRoot(), "mods"); +} + +QString LegacyInstance::coreModsDir() const +{ + return FS::PathCombine(minecraftRoot(), "coremods"); +} + +QString LegacyInstance::resourceDir() const +{ + return FS::PathCombine(minecraftRoot(), "resources"); +} +QString LegacyInstance::texturePacksDir() const +{ + return FS::PathCombine(minecraftRoot(), "texturepacks"); +} + +QString LegacyInstance::runnableJar() const +{ + return FS::PathCombine(binRoot(), "minecraft.jar"); +} + +QString LegacyInstance::modListFile() const +{ + return FS::PathCombine(instanceRoot(), "modlist"); +} + +QString LegacyInstance::instanceConfigFolder() const +{ + return FS::PathCombine(minecraftRoot(), "config"); +} + +bool LegacyInstance::shouldRebuild() const +{ + return m_settings->get("NeedsRebuild").toBool(); +} + +QString LegacyInstance::currentVersionId() const +{ + return m_settings->get("JarVersion").toString(); +} + +QString LegacyInstance::intendedVersionId() const +{ + return m_settings->get("IntendedJarVersion").toString(); +} + +bool LegacyInstance::shouldUpdate() const +{ + QVariant var = settings()->get("ShouldUpdate"); + if (!var.isValid() || var.toBool() == false) + { + return intendedVersionId() != currentVersionId(); + } + return true; +} + +QString LegacyInstance::defaultBaseJar() const +{ + return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar"; +} + +QString LegacyInstance::defaultCustomBaseJar() const +{ + return FS::PathCombine(binRoot(), "mcbackup.jar"); +} + +QString LegacyInstance::typeName() const +{ + return tr("Legacy"); +} + +QString LegacyInstance::getStatusbarDescription() +{ + return tr("Instance from previous versions."); +} + +QStringList LegacyInstance::verboseDescription(AuthSessionPtr session) +{ + QStringList out; + + auto alltraits = traits(); + if(alltraits.size()) + { + out << "Traits:"; + for (auto trait : alltraits) + { + out << " " + trait; + } + out << ""; + } + + QString windowParams; + if (settings()->get("LaunchMaximized").toBool()) + { + out << "Window size: max (if available)"; + } + else + { + auto width = settings()->get("MinecraftWinWidth").toInt(); + auto height = settings()->get("MinecraftWinHeight").toInt(); + out << "Window size: " + QString::number(width) + " x " + QString::number(height); + } + out << ""; + return out; +} diff --git a/api/logic/minecraft/legacy/LegacyInstance.h b/api/logic/minecraft/legacy/LegacyInstance.h new file mode 100644 index 00000000..9c5cedd3 --- /dev/null +++ b/api/logic/minecraft/legacy/LegacyInstance.h @@ -0,0 +1,128 @@ +/* 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. + */ + +#pragma once + +#include "BaseInstance.h" +#include "minecraft/Mod.h" + +#include "multimc_logic_export.h" + +class ModList; +class LegacyModList; +class Task; +/* + * WHY: Legacy instances - from MultiMC 3 and 4 - are here only to provide a way to upgrade them to the current format. + */ +class MULTIMC_LOGIC_EXPORT LegacyInstance : public BaseInstance +{ + Q_OBJECT +public: + + explicit LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir); + + virtual void init() override {}; + + /// Path to the instance's minecraft.jar + QString runnableJar() const; + + //! Path to the instance's modlist file. + QString modListFile() const; + + ////// Directories ////// + QString libDir() const; + QString savesDir() const; + QString texturePacksDir() const; + QString jarModsDir() const; + QString loaderModsDir() const; + QString coreModsDir() const; + QString resourceDir() const; + virtual QString instanceConfigFolder() const override; + QString minecraftRoot() const; // Path to the instance's minecraft directory. + QString binRoot() const; // Path to the instance's minecraft bin directory. + + /// Get the curent base jar of this instance. By default, it's the + /// versions/$version/$version.jar + QString baseJar() const; + + /// the default base jar of this instance + QString defaultBaseJar() const; + /// the default custom base jar of this instance + QString defaultCustomBaseJar() const; + + /*! + * Whether or not custom base jar is used + */ + bool shouldUseCustomBaseJar() const; + + /*! + * The value of the custom base jar + */ + QString customBaseJar() const; + + std::shared_ptr<LegacyModList> jarModList() const; + QList<Mod> getJarMods() const; + + /*! + * Whether or not the instance's minecraft.jar needs to be rebuilt. + * If this is true, when the instance launches, its jar mods will be + * re-added to a fresh minecraft.jar file. + */ + bool shouldRebuild() const; + + QString currentVersionId() const; + QString intendedVersionId() const; + + QSet<QString> traits() override + { + return {"legacy-instance", "texturepacks"}; + }; + + virtual bool shouldUpdate() const; + virtual shared_qobject_ptr<Task> createUpdateTask() override; + + virtual QString typeName() const override; + + bool canExport() const override + { + return false; + } + std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override + { + return nullptr; + } + IPathMatcher::Ptr getLogFileMatcher() override + { + return nullptr; + } + QString getLogFileRoot() override + { + return minecraftRoot(); + } + + QString getStatusbarDescription() override; + QStringList verboseDescription(AuthSessionPtr session) override; + + QProcessEnvironment createEnvironment() override + { + return QProcessEnvironment(); + } + QMap<QString, QString> getVariables() const override + { + return {}; + } +protected: + mutable std::shared_ptr<LegacyModList> jar_mod_list; +}; 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; +} diff --git a/api/logic/minecraft/legacy/LegacyModList.h b/api/logic/minecraft/legacy/LegacyModList.h new file mode 100644 index 00000000..3fe90ac3 --- /dev/null +++ b/api/logic/minecraft/legacy/LegacyModList.h @@ -0,0 +1,56 @@ +/* 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. + */ + +#pragma once + +#include <QList> +#include <QString> +#include <QDir> + +#include "minecraft/Mod.h" + +#include "multimc_logic_export.h" + +class LegacyInstance; +class BaseInstance; + +/** + * A legacy mod list. + * Backed by a folder. + */ +class MULTIMC_LOGIC_EXPORT LegacyModList +{ +public: + + LegacyModList(const QString &dir, const QString &list_file = QString()); + + /// Reloads the mod list and returns true if the list changed. + bool update(); + + QDir dir() + { + return m_dir; + } + + const QList<Mod> & allMods() + { + return mods; + } + +protected: + QDir m_dir; + QString m_list_file; + QList<Mod> mods; +}; |