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 m_metacache; std::shared_ptr m_iconlist; shared_qobject_ptr m_metadataIndex; - // FIXME: replace with mojang format LWJGL in meta store - std::shared_ptr 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 @@ -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 +#include +#include +#include + +#include "LegacyInstance.h" + +#include "minecraft/legacy/LegacyModList.h" +#include "minecraft/ModList.h" +#include "minecraft/WorldList.h" +#include +#include + +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 LegacyInstance::createUpdateTask() +{ + return nullptr; +} + +/* +class LegacyJarModTask : public Task +{ + //Q_OBJECT +public: + explicit LegacyJarModTask(std::shared_ptr 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 m_inst; +}; +*/ + +std::shared_ptr 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 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 jarModList() const; + QList 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 traits() override + { + return {"legacy-instance", "texturepacks"}; + }; + + virtual bool shouldUpdate() const; + virtual shared_qobject_ptr createUpdateTask() override; + + virtual QString typeName() const override; + + bool canExport() const override + { + return false; + } + std::shared_ptr 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 getVariables() const override + { + return {}; + } +protected: + mutable std::shared_ptr 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 +#include +#include + +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 OrderList; + +static void internalSort(QList &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 orderedMods; + QList 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 +#include +#include + +#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 & allMods() + { + return mods; + } + +protected: + QDir m_dir; + QString m_list_file; + QList mods; +}; diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index 70cb1e93..17e19b58 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -131,6 +131,8 @@ SET(MULTIMC_SOURCES pages/ScreenshotsPage.h pages/OtherLogsPage.cpp pages/OtherLogsPage.h + pages/LegacyUpgradePage.cpp + pages/LegacyUpgradePage.h pages/WorldListPage.cpp pages/WorldListPage.h @@ -229,7 +231,7 @@ SET(MULTIMC_SOURCES ######## UIs ######## SET(MULTIMC_UIS - # Option pages + # Instance pages pages/VersionPage.ui pages/ModFolderPage.ui pages/LogPage.ui @@ -237,6 +239,7 @@ SET(MULTIMC_UIS pages/NotesPage.ui pages/ScreenshotsPage.ui pages/OtherLogsPage.ui + pages/LegacyUpgradePage.ui pages/WorldListPage.ui # Global settings pages diff --git a/application/InstancePageProvider.h b/application/InstancePageProvider.h index ac5306c0..3b361e3e 100644 --- a/application/InstancePageProvider.h +++ b/application/InstancePageProvider.h @@ -1,5 +1,6 @@ #pragma once #include "minecraft/MinecraftInstance.h" +#include "minecraft/legacy/LegacyInstance.h" #include #include "pages/BasePage.h" #include "pages/LogPage.h" @@ -12,6 +13,7 @@ #include "pages/InstanceSettingsPage.h" #include "pages/OtherLogsPage.h" #include "pages/BasePageProvider.h" +#include "pages/LegacyUpgradePage.h" #include "pages/WorldListPage.h" @@ -44,6 +46,11 @@ public: values.append(new ScreenshotsPage(FS::PathCombine(onesix->minecraftRoot(), "screenshots"))); values.append(new InstanceSettingsPage(onesix.get())); } + std::shared_ptr legacy = std::dynamic_pointer_cast(inst); + if(legacy) + { + values.append(new LegacyUpgradePage(legacy.get())); + } auto logMatcher = inst->getLogFileMatcher(); if(logMatcher) { diff --git a/application/pages/LegacyUpgradePage.cpp b/application/pages/LegacyUpgradePage.cpp new file mode 100644 index 00000000..14cb916d --- /dev/null +++ b/application/pages/LegacyUpgradePage.cpp @@ -0,0 +1,25 @@ +#include "LegacyUpgradePage.h" +#include "ui_LegacyUpgradePage.h" + +#include "minecraft/legacy/LegacyInstance.h" + +LegacyUpgradePage::LegacyUpgradePage(LegacyInstance *inst, QWidget *parent) + : QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst) +{ + ui->setupUi(this); +} + +LegacyUpgradePage::~LegacyUpgradePage() +{ + delete ui; +} + +void LegacyUpgradePage::on_upgradeButton_clicked() +{ + // now what? +} + +bool LegacyUpgradePage::shouldDisplay() const +{ + return !m_inst->isRunning(); +} diff --git a/application/pages/LegacyUpgradePage.h b/application/pages/LegacyUpgradePage.h new file mode 100644 index 00000000..4731bb82 --- /dev/null +++ b/application/pages/LegacyUpgradePage.h @@ -0,0 +1,60 @@ +/* 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 + +#include "minecraft/legacy/LegacyInstance.h" +#include "pages/BasePage.h" +#include + +namespace Ui +{ +class LegacyUpgradePage; +} + +class LegacyUpgradePage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit LegacyUpgradePage(LegacyInstance *inst, QWidget *parent = 0); + virtual ~LegacyUpgradePage(); + virtual QString displayName() const override + { + return tr("Upgrade"); + } + virtual QIcon icon() const override + { + return MMC->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: + Ui::LegacyUpgradePage *ui; + LegacyInstance *m_inst; +}; diff --git a/application/pages/LegacyUpgradePage.ui b/application/pages/LegacyUpgradePage.ui new file mode 100644 index 00000000..124a0ce9 --- /dev/null +++ b/application/pages/LegacyUpgradePage.ui @@ -0,0 +1,47 @@ + + + LegacyUpgradePage + + + + 0 + 0 + 546 + 405 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + <html><body><h1>Upgrade is required</h1><p>MultiMC 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>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>Please report any issues on our <a href="https://github.com/MultiMC/MultiMC5/issues">github issues page</a>.</p></body></html> + + + true + + + + + + + Upgrade the instance + + + + + + + +