refactor: drop LegacyInstance
This commit is contained in:
		| @@ -286,13 +286,6 @@ set(MINECRAFT_SOURCES | ||||
|     minecraft/launch/VerifyJavaInstall.cpp | ||||
|     minecraft/launch/VerifyJavaInstall.h | ||||
|  | ||||
|     minecraft/legacy/LegacyModList.h | ||||
|     minecraft/legacy/LegacyModList.cpp | ||||
|     minecraft/legacy/LegacyInstance.h | ||||
|     minecraft/legacy/LegacyInstance.cpp | ||||
|     minecraft/legacy/LegacyUpgradeTask.h | ||||
|     minecraft/legacy/LegacyUpgradeTask.cpp | ||||
|  | ||||
|     minecraft/GradleSpecifier.h | ||||
|     minecraft/MinecraftInstance.cpp | ||||
|     minecraft/MinecraftInstance.h | ||||
| @@ -701,8 +694,6 @@ SET(LAUNCHER_SOURCES | ||||
|     ui/pages/instance/OtherLogsPage.h | ||||
|     ui/pages/instance/ServersPage.cpp | ||||
|     ui/pages/instance/ServersPage.h | ||||
|     ui/pages/instance/LegacyUpgradePage.cpp | ||||
|     ui/pages/instance/LegacyUpgradePage.h | ||||
|     ui/pages/instance/WorldListPage.cpp | ||||
|     ui/pages/instance/WorldListPage.h | ||||
|  | ||||
| @@ -884,7 +875,6 @@ qt5_wrap_ui(LAUNCHER_UI | ||||
|     ui/pages/instance/InstanceSettingsPage.ui | ||||
|     ui/pages/instance/VersionPage.ui | ||||
|     ui/pages/instance/WorldListPage.ui | ||||
|     ui/pages/instance/LegacyUpgradePage.ui | ||||
|     ui/pages/instance/ScreenshotsPage.ui | ||||
|     ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui | ||||
|     ui/pages/modplatform/atlauncher/AtlPage.ui | ||||
|   | ||||
| @@ -32,7 +32,6 @@ | ||||
| #include "BaseInstance.h" | ||||
| #include "InstanceTask.h" | ||||
| #include "settings/INISettingsObject.h" | ||||
| #include "minecraft/legacy/LegacyInstance.h" | ||||
| #include "NullInstance.h" | ||||
| #include "minecraft/MinecraftInstance.h" | ||||
| #include "FileSystem.h" | ||||
| @@ -553,10 +552,6 @@ InstancePtr InstanceList::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)); | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| #pragma once | ||||
| #include "minecraft/MinecraftInstance.h" | ||||
| #include "minecraft/legacy/LegacyInstance.h" | ||||
| #include <FileSystem.h> | ||||
| #include "ui/pages/BasePage.h" | ||||
| #include "ui/pages/BasePageProvider.h" | ||||
| @@ -14,7 +13,6 @@ | ||||
| #include "ui/pages/instance/ScreenshotsPage.h" | ||||
| #include "ui/pages/instance/InstanceSettingsPage.h" | ||||
| #include "ui/pages/instance/OtherLogsPage.h" | ||||
| #include "ui/pages/instance/LegacyUpgradePage.h" | ||||
| #include "ui/pages/instance/WorldListPage.h" | ||||
| #include "ui/pages/instance/ServersPage.h" | ||||
| #include "ui/pages/instance/GameOptionsPage.h" | ||||
| @@ -34,31 +32,20 @@ public: | ||||
|         QList<BasePage *> values; | ||||
|         values.append(new LogPage(inst)); | ||||
|         std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst); | ||||
|         if(onesix) | ||||
|         { | ||||
|             values.append(new VersionPage(onesix.get())); | ||||
|             auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Mods"), "Loader-mods"); | ||||
|             modsPage->setFilter("%1 (*.zip *.jar *.litemod)"); | ||||
|             values.append(modsPage); | ||||
|             values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods")); | ||||
|             values.append(new ResourcePackPage(onesix.get())); | ||||
|             values.append(new TexturePackPage(onesix.get())); | ||||
|             values.append(new ShaderPackPage(onesix.get())); | ||||
|             values.append(new NotesPage(onesix.get())); | ||||
|             values.append(new WorldListPage(onesix.get(), onesix->worldList())); | ||||
|             values.append(new ServersPage(onesix)); | ||||
|             // values.append(new GameOptionsPage(onesix.get())); | ||||
|             values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); | ||||
|             values.append(new InstanceSettingsPage(onesix.get())); | ||||
|         } | ||||
|         std::shared_ptr<LegacyInstance> legacy = std::dynamic_pointer_cast<LegacyInstance>(inst); | ||||
|         if(legacy) | ||||
|         { | ||||
|             values.append(new LegacyUpgradePage(legacy)); | ||||
|             values.append(new NotesPage(legacy.get())); | ||||
|             values.append(new WorldListPage(legacy.get(), legacy->worldList())); | ||||
|             values.append(new ScreenshotsPage(FS::PathCombine(legacy->gameRoot(), "screenshots"))); | ||||
|         } | ||||
|         values.append(new VersionPage(onesix.get())); | ||||
|         auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Mods"), "Loader-mods"); | ||||
|         modsPage->setFilter("%1 (*.zip *.jar *.litemod)"); | ||||
|         values.append(modsPage); | ||||
|         values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods")); | ||||
|         values.append(new ResourcePackPage(onesix.get())); | ||||
|         values.append(new TexturePackPage(onesix.get())); | ||||
|         values.append(new ShaderPackPage(onesix.get())); | ||||
|         values.append(new NotesPage(onesix.get())); | ||||
|         values.append(new WorldListPage(onesix.get(), onesix->worldList())); | ||||
|         values.append(new ServersPage(onesix)); | ||||
|         // values.append(new GameOptionsPage(onesix.get())); | ||||
|         values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); | ||||
|         values.append(new InstanceSettingsPage(onesix.get())); | ||||
|         auto logMatcher = inst->getLogFileMatcher(); | ||||
|         if(logMatcher) | ||||
|         { | ||||
|   | ||||
| @@ -1,256 +0,0 @@ | ||||
| /* 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 <QFileInfo> | ||||
| #include <minecraft/launch/LauncherPartLaunch.h> | ||||
| #include <QDir> | ||||
| #include <settings/Setting.h> | ||||
|  | ||||
| #include "LegacyInstance.h" | ||||
|  | ||||
| #include "minecraft/legacy/LegacyModList.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", QString()); | ||||
|     settings->registerSetting("IntendedJarVersion", QString()); | ||||
|     /* | ||||
|      * 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::mainJarToPreserve() const | ||||
| { | ||||
|     bool customJar = m_settings->get("UseCustomBaseJar").toBool(); | ||||
|     if(customJar) | ||||
|     { | ||||
|         auto base = baseJar(); | ||||
|         if(QFile::exists(base)) | ||||
|         { | ||||
|             return base; | ||||
|         } | ||||
|     } | ||||
|     auto runnable = runnableJar(); | ||||
|     if(QFile::exists(runnable)) | ||||
|     { | ||||
|         return runnable; | ||||
|     } | ||||
|     return QString(); | ||||
| } | ||||
|  | ||||
|  | ||||
| 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(); | ||||
| } | ||||
|  | ||||
|  | ||||
| Task::Ptr LegacyInstance::createUpdateTask(Net::Mode) | ||||
| { | ||||
|     return nullptr; | ||||
| } | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::gameRoot() const | ||||
| { | ||||
|     QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft")); | ||||
|     QFileInfo dotMCDir(FS::PathCombine(instanceRoot(), ".minecraft")); | ||||
|  | ||||
|     if (mcDir.exists() && !dotMCDir.exists()) | ||||
|         return mcDir.filePath(); | ||||
|     else | ||||
|         return dotMCDir.filePath(); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::binRoot() const | ||||
| { | ||||
|     return FS::PathCombine(gameRoot(), "bin"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::modsRoot() const { | ||||
|     return FS::PathCombine(gameRoot(), "mods"); | ||||
| } | ||||
|  | ||||
|  | ||||
| QString LegacyInstance::jarModsDir() const | ||||
| { | ||||
|     return FS::PathCombine(instanceRoot(), "instMods"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::libDir() const | ||||
| { | ||||
|     return FS::PathCombine(gameRoot(), "lib"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::savesDir() const | ||||
| { | ||||
|     return FS::PathCombine(gameRoot(), "saves"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::coreModsDir() const | ||||
| { | ||||
|     return FS::PathCombine(gameRoot(), "coremods"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::resourceDir() const | ||||
| { | ||||
|     return FS::PathCombine(gameRoot(), "resources"); | ||||
| } | ||||
| QString LegacyInstance::texturePacksDir() const | ||||
| { | ||||
|     return FS::PathCombine(gameRoot(), "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(gameRoot(), "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"); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<WorldList> LegacyInstance::worldList() const | ||||
| { | ||||
|     if (!m_world_list) | ||||
|     { | ||||
|         m_world_list.reset(new WorldList(savesDir())); | ||||
|     } | ||||
|     return m_world_list; | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::typeName() const | ||||
| { | ||||
|     return tr("Legacy"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::getStatusbarDescription() | ||||
| { | ||||
|     return tr("Instance from previous versions."); | ||||
| } | ||||
|  | ||||
| QStringList LegacyInstance::verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) | ||||
| { | ||||
|     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; | ||||
| } | ||||
| @@ -1,142 +0,0 @@ | ||||
| /* 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. | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "BaseInstance.h" | ||||
| #include "launch/LaunchTask.h" | ||||
|  | ||||
| class ModFolderModel; | ||||
| class LegacyModList; | ||||
| class WorldList; | ||||
| 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 LegacyInstance : public BaseInstance | ||||
| { | ||||
|     Q_OBJECT | ||||
| public: | ||||
|  | ||||
|     explicit LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir); | ||||
|  | ||||
|     virtual void saveNow() 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 coreModsDir() const; | ||||
|     QString resourceDir() const; | ||||
|  | ||||
|     QString instanceConfigFolder() const override; | ||||
|  | ||||
|     QString gameRoot() const override; // Path to the instance's minecraft directory. | ||||
|     QString modsRoot() const override; // 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; | ||||
|  | ||||
|     // the main jar that we actually want to keep when migrating the instance | ||||
|     QString mainJarToPreserve() 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; | ||||
|     std::shared_ptr<WorldList> worldList() 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() const override | ||||
|     { | ||||
|         return {"legacy-instance", "texturepacks"}; | ||||
|     }; | ||||
|  | ||||
|     virtual bool shouldUpdate() const; | ||||
|     virtual Task::Ptr createUpdateTask(Net::Mode mode) override; | ||||
|  | ||||
|     virtual QString typeName() const override; | ||||
|  | ||||
|     bool canLaunch() const override | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|     bool canEdit() const override | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|     bool canExport() const override | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|     shared_qobject_ptr<LaunchTask> createLaunchTask( | ||||
|             AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override | ||||
|     { | ||||
|         return nullptr; | ||||
|     } | ||||
|     IPathMatcher::Ptr getLogFileMatcher() override | ||||
|     { | ||||
|         return nullptr; | ||||
|     } | ||||
|     QString getLogFileRoot() override | ||||
|     { | ||||
|         return gameRoot(); | ||||
|     } | ||||
|  | ||||
|     QString getStatusbarDescription() override; | ||||
|     QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override; | ||||
|  | ||||
|     QProcessEnvironment createEnvironment() override | ||||
|     { | ||||
|         return QProcessEnvironment(); | ||||
|     } | ||||
|     QMap<QString, QString> getVariables() const override | ||||
|     { | ||||
|         return {}; | ||||
|     } | ||||
| protected: | ||||
|     mutable std::shared_ptr<LegacyModList> jar_mod_list; | ||||
|     mutable std::shared_ptr<WorldList> m_world_list; | ||||
| }; | ||||
| @@ -1,136 +0,0 @@ | ||||
| /* 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); | ||||
|     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; | ||||
| } | ||||
| @@ -1,47 +0,0 @@ | ||||
| /* 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. | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <QList> | ||||
| #include <QString> | ||||
| #include <QDir> | ||||
|  | ||||
| class LegacyModList | ||||
| { | ||||
| public: | ||||
|  | ||||
|     using Mod = QFileInfo; | ||||
|  | ||||
|     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; | ||||
| }; | ||||
| @@ -1,138 +0,0 @@ | ||||
| #include "LegacyUpgradeTask.h" | ||||
| #include "settings/INISettingsObject.h" | ||||
| #include "FileSystem.h" | ||||
| #include "NullInstance.h" | ||||
| #include "pathmatcher/RegexpMatcher.h" | ||||
| #include <QtConcurrentRun> | ||||
| #include "LegacyInstance.h" | ||||
| #include "minecraft/MinecraftInstance.h" | ||||
| #include "minecraft/PackProfile.h" | ||||
| #include "LegacyModList.h" | ||||
| #include "classparser.h" | ||||
|  | ||||
| LegacyUpgradeTask::LegacyUpgradeTask(InstancePtr origInstance) | ||||
| { | ||||
|     m_origInstance = origInstance; | ||||
| } | ||||
|  | ||||
| void LegacyUpgradeTask::executeTask() | ||||
| { | ||||
|     setStatus(tr("Copying instance %1").arg(m_origInstance->name())); | ||||
|  | ||||
|     FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath); | ||||
|     folderCopy.followSymlinks(true); | ||||
|  | ||||
|     m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy); | ||||
|     connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &LegacyUpgradeTask::copyFinished); | ||||
|     connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &LegacyUpgradeTask::copyAborted); | ||||
|     m_copyFutureWatcher.setFuture(m_copyFuture); | ||||
| } | ||||
|  | ||||
| static QString decideVersion(const QString& currentVersion, const QString& intendedVersion) | ||||
| { | ||||
|     if(intendedVersion != currentVersion) | ||||
|     { | ||||
|         if(!intendedVersion.isEmpty()) | ||||
|         { | ||||
|             return intendedVersion; | ||||
|         } | ||||
|         else if(!currentVersion.isEmpty()) | ||||
|         { | ||||
|             return currentVersion; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if(!intendedVersion.isEmpty()) | ||||
|         { | ||||
|             return intendedVersion; | ||||
|         } | ||||
|     } | ||||
|     return QString(); | ||||
| } | ||||
|  | ||||
| void LegacyUpgradeTask::copyFinished() | ||||
| { | ||||
|     auto successful = m_copyFuture.result(); | ||||
|     if(!successful) | ||||
|     { | ||||
|         emitFailed(tr("Instance folder copy failed.")); | ||||
|         return; | ||||
|     } | ||||
|     auto legacyInst = std::dynamic_pointer_cast<LegacyInstance>(m_origInstance); | ||||
|  | ||||
|     auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg")); | ||||
|     instanceSettings->registerSetting("InstanceType", "Legacy"); | ||||
|     instanceSettings->set("InstanceType", "OneSix"); | ||||
|     // NOTE: this scope ensures the instance is fully saved before we emitSucceeded | ||||
|     { | ||||
|         MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath); | ||||
|         inst.setName(m_instName); | ||||
|  | ||||
|         QString preferredVersionNumber = decideVersion(legacyInst->currentVersionId(), legacyInst->intendedVersionId()); | ||||
|         if(preferredVersionNumber.isNull()) | ||||
|         { | ||||
|             // try to decide version based on the jar(s?) | ||||
|             preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->baseJar()); | ||||
|             if(preferredVersionNumber.isNull()) | ||||
|             { | ||||
|                 preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->runnableJar()); | ||||
|                 if(preferredVersionNumber.isNull()) | ||||
|                 { | ||||
|                     emitFailed(tr("Could not decide Minecraft version.")); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         auto components = inst.getPackProfile(); | ||||
|         components->buildingFromScratch(); | ||||
|         components->setComponentVersion("net.minecraft", preferredVersionNumber, true); | ||||
|  | ||||
|         QString jarPath = legacyInst->mainJarToPreserve(); | ||||
|         if(!jarPath.isNull()) | ||||
|         { | ||||
|             qDebug() << "Preserving base jar! : " << jarPath; | ||||
|             // FIXME: handle case when the jar is unreadable? | ||||
|             // TODO: check the hash, if it's the same as the upstream jar, do not do this | ||||
|             components->installCustomJar(jarPath); | ||||
|         } | ||||
|  | ||||
|         auto jarMods = legacyInst->jarModList()->allMods(); | ||||
|         for(auto & jarMod: jarMods) | ||||
|         { | ||||
|             QString modPath = jarMod.absoluteFilePath(); | ||||
|             qDebug() << "jarMod: " << modPath; | ||||
|             components->installJarMods({modPath}); | ||||
|         } | ||||
|  | ||||
|         // remove all the extra garbage we no longer need | ||||
|         auto removeAll = [&](const QString &root, const QStringList &things) | ||||
|         { | ||||
|             for(auto &thing : things) | ||||
|             { | ||||
|                 auto removePath = FS::PathCombine(root, thing); | ||||
|                 QFileInfo stat(removePath); | ||||
|                 if(stat.isDir()) | ||||
|                 { | ||||
|                     FS::deletePath(removePath); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     QFile::remove(removePath); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|         QStringList rootRemovables = {"modlist", "version", "instMods"}; | ||||
|         QStringList mcRemovables = {"bin", "MultiMCLauncher.jar", "icon.png"}; | ||||
|         removeAll(inst.instanceRoot(), rootRemovables); | ||||
|         removeAll(inst.gameRoot(), mcRemovables); | ||||
|     } | ||||
|     emitSucceeded(); | ||||
| } | ||||
|  | ||||
| void LegacyUpgradeTask::copyAborted() | ||||
| { | ||||
|     emitFailed(tr("Instance folder copy has been aborted.")); | ||||
|     return; | ||||
| } | ||||
|  | ||||
| @@ -1,29 +0,0 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "InstanceTask.h" | ||||
| #include "net/NetJob.h" | ||||
| #include <QUrl> | ||||
| #include <QFuture> | ||||
| #include <QFutureWatcher> | ||||
| #include "settings/SettingsObject.h" | ||||
| #include "BaseVersion.h" | ||||
| #include "BaseInstance.h" | ||||
|  | ||||
|  | ||||
| class LegacyUpgradeTask : public InstanceTask | ||||
| { | ||||
|     Q_OBJECT | ||||
| public: | ||||
|     explicit LegacyUpgradeTask(InstancePtr origInstance); | ||||
|  | ||||
| protected: | ||||
|     //! Entry point for tasks. | ||||
|     virtual void executeTask() override; | ||||
|     void copyFinished(); | ||||
|     void copyAborted(); | ||||
|  | ||||
| private: /* data */ | ||||
|     InstancePtr m_origInstance; | ||||
|     QFuture<bool> m_copyFuture; | ||||
|     QFutureWatcher<bool> m_copyFutureWatcher; | ||||
| }; | ||||
| @@ -1,51 +0,0 @@ | ||||
| #include "LegacyUpgradePage.h" | ||||
| #include "ui_LegacyUpgradePage.h" | ||||
|  | ||||
| #include "InstanceList.h" | ||||
| #include "minecraft/legacy/LegacyInstance.h" | ||||
| #include "minecraft/legacy/LegacyUpgradeTask.h" | ||||
| #include "Application.h" | ||||
|  | ||||
| #include "ui/dialogs/CustomMessageBox.h" | ||||
| #include "ui/dialogs/ProgressDialog.h" | ||||
|  | ||||
| LegacyUpgradePage::LegacyUpgradePage(InstancePtr inst, QWidget *parent) | ||||
|     : QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst) | ||||
| { | ||||
|     ui->setupUi(this); | ||||
| } | ||||
|  | ||||
| LegacyUpgradePage::~LegacyUpgradePage() | ||||
| { | ||||
|     delete ui; | ||||
| } | ||||
|  | ||||
| void LegacyUpgradePage::runModalTask(Task *task) | ||||
| { | ||||
|     connect(task, &Task::failed, [this](QString reason) | ||||
|         { | ||||
|             CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Warning)->show(); | ||||
|         }); | ||||
|     ProgressDialog loadDialog(this); | ||||
|     loadDialog.setSkipButton(true, tr("Abort")); | ||||
|     if(loadDialog.execWithTask(task) == QDialog::Accepted) | ||||
|     { | ||||
|         m_container->requestClose(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void LegacyUpgradePage::on_upgradeButton_clicked() | ||||
| { | ||||
|     QString newName = tr("%1 (Migrated)").arg(m_inst->name()); | ||||
|     auto upgradeTask = new LegacyUpgradeTask(m_inst); | ||||
|     upgradeTask->setName(newName); | ||||
|     upgradeTask->setGroup(APPLICATION->instances()->getInstanceGroup(m_inst->id())); | ||||
|     upgradeTask->setIcon(m_inst->iconKey()); | ||||
|     unique_qobject_ptr<Task> task(APPLICATION->instances()->wrapInstanceTask(upgradeTask)); | ||||
|     runModalTask(task.get()); | ||||
| } | ||||
|  | ||||
| bool LegacyUpgradePage::shouldDisplay() const | ||||
| { | ||||
|     return !m_inst->isRunning(); | ||||
| } | ||||
| @@ -1,64 +0,0 @@ | ||||
| /* 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. | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <QWidget> | ||||
|  | ||||
| #include "minecraft/legacy/LegacyInstance.h" | ||||
| #include "ui/pages/BasePage.h" | ||||
| #include <Application.h> | ||||
| #include "tasks/Task.h" | ||||
|  | ||||
| namespace Ui | ||||
| { | ||||
| class LegacyUpgradePage; | ||||
| } | ||||
|  | ||||
| class LegacyUpgradePage : public QWidget, public BasePage | ||||
| { | ||||
|     Q_OBJECT | ||||
|  | ||||
| public: | ||||
|     explicit LegacyUpgradePage(InstancePtr inst, QWidget *parent = 0); | ||||
|     virtual ~LegacyUpgradePage(); | ||||
|     virtual QString displayName() const override | ||||
|     { | ||||
|         return tr("Upgrade"); | ||||
|     } | ||||
|     virtual QIcon icon() const override | ||||
|     { | ||||
|         return APPLICATION->getThemedIcon("checkupdate"); | ||||
|     } | ||||
|     virtual QString id() const override | ||||
|     { | ||||
|         return "upgrade"; | ||||
|     } | ||||
|     virtual QString helpPage() const override | ||||
|     { | ||||
|         return "Legacy-upgrade"; | ||||
|     } | ||||
|     virtual bool shouldDisplay() const override; | ||||
|  | ||||
| private slots: | ||||
|     void on_upgradeButton_clicked(); | ||||
|  | ||||
| private: | ||||
|     void runModalTask(Task *task); | ||||
|  | ||||
| private: | ||||
|     Ui::LegacyUpgradePage *ui; | ||||
|     InstancePtr m_inst; | ||||
| }; | ||||
| @@ -1,54 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|  <class>LegacyUpgradePage</class> | ||||
|  <widget class="QWidget" name="LegacyUpgradePage"> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>546</width> | ||||
|     <height>405</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout" name="verticalLayout_5"> | ||||
|    <property name="leftMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <property name="topMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <property name="rightMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <property name="bottomMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <item> | ||||
|     <widget class="QTextBrowser" name="textBrowser"> | ||||
|      <property name="html"> | ||||
|       <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> | ||||
| <html><head><meta name="qrichtext" content="1" /><style type="text/css"> | ||||
| p, li { white-space: pre-wrap; } | ||||
| </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> | ||||
| <h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:600;">Upgrade is required</span></h1> | ||||
| <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">PolyMC now supports old Minecraft versions and all the required features in the new (OneSix) instance format. As a consequence, the old (Legacy) format has been entirely disabled and old instances need to be upgraded.</p> | ||||
| <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The upgrade will create a new instance with the same contents as the current one, in the new format. The original instance will remain untouched, in case anything goes wrong in the process.</p> | ||||
| <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Please report any issues on our <a href="https://github.com/PolyMC/PolyMC/issues"><span style=" text-decoration: underline; color:#3584e4;">github issues page</span></a>.</p></body></html></string> | ||||
|      </property> | ||||
|      <property name="openExternalLinks"> | ||||
|       <bool>true</bool> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <widget class="QCommandLinkButton" name="upgradeButton"> | ||||
|      <property name="text"> | ||||
|       <string>Upgrade the instance</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
| </ui> | ||||
		Reference in New Issue
	
	Block a user