aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildconfig/BuildConfig.h2
-rw-r--r--launcher/BaseInstance.cpp1
-rw-r--r--launcher/CMakeLists.txt10
-rw-r--r--launcher/InstanceCopyTask.cpp1
-rw-r--r--launcher/InstanceCreationTask.cpp2
-rw-r--r--launcher/InstanceImportTask.cpp3
-rw-r--r--launcher/InstanceList.cpp7
-rw-r--r--launcher/InstancePageProvider.h41
-rw-r--r--launcher/ModDownloadTask.h1
-rw-r--r--launcher/minecraft/MinecraftInstance.cpp11
-rw-r--r--launcher/minecraft/PackProfile.cpp254
-rw-r--r--launcher/minecraft/PackProfile.h2
-rw-r--r--launcher/minecraft/PackProfile_p.h12
-rw-r--r--launcher/minecraft/legacy/LegacyInstance.cpp256
-rw-r--r--launcher/minecraft/legacy/LegacyInstance.h142
-rw-r--r--launcher/minecraft/legacy/LegacyModList.cpp136
-rw-r--r--launcher/minecraft/legacy/LegacyModList.h47
-rw-r--r--launcher/minecraft/legacy/LegacyUpgradeTask.cpp138
-rw-r--r--launcher/minecraft/legacy/LegacyUpgradeTask.h29
-rw-r--r--launcher/modplatform/atlauncher/ATLPackInstallTask.cpp2
-rw-r--r--launcher/modplatform/legacy_ftb/PackInstallTask.cpp2
-rw-r--r--launcher/modplatform/modpacksch/FTBPackInstallTask.cpp2
-rw-r--r--launcher/modplatform/technic/TechnicPackProcessor.cpp2
-rw-r--r--launcher/ui/dialogs/ModDownloadDialog.cpp64
-rw-r--r--launcher/ui/dialogs/ModDownloadDialog.h9
-rw-r--r--launcher/ui/pages/instance/LegacyUpgradePage.cpp51
-rw-r--r--launcher/ui/pages/instance/LegacyUpgradePage.h64
-rw-r--r--launcher/ui/pages/instance/LegacyUpgradePage.ui54
-rw-r--r--launcher/ui/pages/instance/ModFolderPage.cpp3
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModPage.cpp344
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModPage.h3
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModPage.ui179
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp318
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthPage.h3
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui179
35 files changed, 624 insertions, 1750 deletions
diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h
index 111381ab..1c5ff357 100644
--- a/buildconfig/BuildConfig.h
+++ b/buildconfig/BuildConfig.h
@@ -98,7 +98,7 @@ public:
QString AUTH_BASE = "https://authserver.mojang.com/";
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
QString FMLLIBS_BASE_URL = "https://files.multimc.org/fmllibs/";
- QString TRANSLATIONS_BASE_URL = "https://meta.polymc.org/translations/";
+ QString TRANSLATIONS_BASE_URL = "https://i18n.polymc.org/";
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";
diff --git a/launcher/BaseInstance.cpp b/launcher/BaseInstance.cpp
index 374d4a29..1bff9e1d 100644
--- a/launcher/BaseInstance.cpp
+++ b/launcher/BaseInstance.cpp
@@ -39,6 +39,7 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
m_settings->registerSetting("lastLaunchTime", 0);
m_settings->registerSetting("totalTimePlayed", 0);
m_settings->registerSetting("lastTimePlayed", 0);
+ m_settings->registerSetting("InstanceType", "OneSix");
// Custom Commands
auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 90149c3b..86c05651 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -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
diff --git a/launcher/InstanceCopyTask.cpp b/launcher/InstanceCopyTask.cpp
index 35adeaf9..c2bfe839 100644
--- a/launcher/InstanceCopyTask.cpp
+++ b/launcher/InstanceCopyTask.cpp
@@ -42,7 +42,6 @@ void InstanceCopyTask::copyFinished()
}
// FIXME: shouldn't this be able to report errors?
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
- instanceSettings->registerSetting("InstanceType", "Legacy");
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
inst->setName(m_instName);
diff --git a/launcher/InstanceCreationTask.cpp b/launcher/InstanceCreationTask.cpp
index eafc5126..4c37bd7f 100644
--- a/launcher/InstanceCreationTask.cpp
+++ b/launcher/InstanceCreationTask.cpp
@@ -17,8 +17,6 @@ void InstanceCreationTask::executeTask()
{
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
instanceSettings->suspendSave();
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
auto components = inst.getPackProfile();
components->buildingFromScratch();
diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index ec378538..6dd615c7 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -261,8 +261,6 @@ void InstanceImportTask::processFlame()
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto mcVersion = pack.minecraft.version;
// Hack to correct some 'special sauce'...
@@ -422,7 +420,6 @@ void InstanceImportTask::processMultiMC()
{
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
- instanceSettings->registerSetting("InstanceType", "Legacy");
NullInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp
index ad18740b..04b86f6b 100644
--- a/launcher/InstanceList.cpp
+++ b/launcher/InstanceList.cpp
@@ -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"
@@ -545,7 +544,7 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id)
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(instanceRoot, "instance.cfg"));
InstancePtr inst;
- instanceSettings->registerSetting("InstanceType", "Legacy");
+ instanceSettings->registerSetting("InstanceType", "Legacy"); // intentionally Legacy. We don't support it.
QString inst_type = instanceSettings->get("InstanceType").toString();
@@ -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));
diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h
index 97eeab8c..357157d0 100644
--- a/launcher/InstancePageProvider.h
+++ b/launcher/InstancePageProvider.h
@@ -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)
{
diff --git a/launcher/ModDownloadTask.h b/launcher/ModDownloadTask.h
index 7e4f1b7d..ddada5a2 100644
--- a/launcher/ModDownloadTask.h
+++ b/launcher/ModDownloadTask.h
@@ -10,6 +10,7 @@ class ModDownloadTask : public Task {
Q_OBJECT
public:
explicit ModDownloadTask(const QUrl sourceUrl, const QString filename, const std::shared_ptr<ModFolderModel> mods);
+ const QString& getFilename() const { return filename; }
public slots:
bool abort() override;
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index 7327f9d5..6db12c42 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -124,18 +124,7 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
m_settings->registerSetting("JoinServerOnLaunch", false);
m_settings->registerSetting("JoinServerOnLaunchAddress", "");
- // DEPRECATED: Read what versions the user configuration thinks should be used
- m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, "");
- m_settings->registerSetting("LWJGLVersion", "");
- m_settings->registerSetting("ForgeVersion", "");
- m_settings->registerSetting("LiteloaderVersion", "");
-
m_components.reset(new PackProfile(this));
- m_components->setOldConfigVersion("net.minecraft", m_settings->get("IntendedVersion").toString());
- auto setting = m_settings->getSetting("LWJGLVersion");
- m_components->setOldConfigVersion("org.lwjgl", m_settings->get("LWJGLVersion").toString());
- m_components->setOldConfigVersion("net.minecraftforge", m_settings->get("ForgeVersion").toString());
- m_components->setOldConfigVersion("com.mumfrey.liteloader", m_settings->get("LiteloaderVersion").toString());
}
void MinecraftInstance::saveNow()
diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp
index 59a8f133..d516e555 100644
--- a/launcher/minecraft/PackProfile.cpp
+++ b/launcher/minecraft/PackProfile.cpp
@@ -272,18 +272,6 @@ void PackProfile::save_internal()
bool PackProfile::load()
{
auto filename = componentsFilePath();
- QFile componentsFile(filename);
-
- // migrate old config to new one, if needed
- if(!componentsFile.exists())
- {
- if(!migratePreComponentConfig())
- {
- // FIXME: the user should be notified...
- qCritical() << "Failed to convert old pre-component config for instance" << d->m_instance->name();
- return false;
- }
- }
// load the new component list and swap it with the current one...
ComponentContainer newComponents;
@@ -369,239 +357,6 @@ void PackProfile::updateFailed(const QString& error)
invalidateLaunchProfile();
}
-// NOTE this is really old stuff, and only needs to be used when loading the old hardcoded component-unaware format (loadPreComponentConfig).
-static void upgradeDeprecatedFiles(QString root, QString instanceName)
-{
- auto versionJsonPath = FS::PathCombine(root, "version.json");
- auto customJsonPath = FS::PathCombine(root, "custom.json");
- auto mcJson = FS::PathCombine(root, "patches" , "net.minecraft.json");
-
- QString sourceFile;
- QString renameFile;
-
- // convert old crap.
- if(QFile::exists(customJsonPath))
- {
- sourceFile = customJsonPath;
- renameFile = versionJsonPath;
- }
- else if(QFile::exists(versionJsonPath))
- {
- sourceFile = versionJsonPath;
- }
- if(!sourceFile.isEmpty() && !QFile::exists(mcJson))
- {
- if(!FS::ensureFilePathExists(mcJson))
- {
- qWarning() << "Couldn't create patches folder for" << instanceName;
- return;
- }
- if(!renameFile.isEmpty() && QFile::exists(renameFile))
- {
- if(!QFile::rename(renameFile, renameFile + ".old"))
- {
- qWarning() << "Couldn't rename" << renameFile << "to" << renameFile + ".old" << "in" << instanceName;
- return;
- }
- }
- auto file = ProfileUtils::parseJsonFile(QFileInfo(sourceFile), false);
- ProfileUtils::removeLwjglFromPatch(file);
- file->uid = "net.minecraft";
- file->version = file->minecraftVersion;
- file->name = "Minecraft";
-
- Meta::Require needsLwjgl;
- needsLwjgl.uid = "org.lwjgl";
- file->requires.insert(needsLwjgl);
-
- if(!ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), mcJson))
- {
- return;
- }
- if(!QFile::rename(sourceFile, sourceFile + ".old"))
- {
- qWarning() << "Couldn't rename" << sourceFile << "to" << sourceFile + ".old" << "in" << instanceName;
- return;
- }
- }
-}
-
-/*
- * Migrate old layout to the component based one...
- * - Part of the version information is taken from `instance.cfg` (fed to this class from outside).
- * - Part is taken from the old order.json file.
- * - Part is loaded from loose json files in the instance's `patches` directory.
- */
-bool PackProfile::migratePreComponentConfig()
-{
- // upgrade the very old files from the beginnings of MultiMC 5
- upgradeDeprecatedFiles(d->m_instance->instanceRoot(), d->m_instance->name());
-
- QList<ComponentPtr> components;
- QSet<QString> loaded;
-
- auto addBuiltinPatch = [&](const QString &uid, bool asDependency, const QString & emptyVersion, const Meta::Require & req, const Meta::Require & conflict)
- {
- auto jsonFilePath = FS::PathCombine(d->m_instance->instanceRoot(), "patches" , uid + ".json");
- auto intendedVersion = d->getOldConfigVersion(uid);
- // load up the base minecraft patch
- ComponentPtr component;
- if(QFile::exists(jsonFilePath))
- {
- if(intendedVersion.isEmpty())
- {
- intendedVersion = emptyVersion;
- }
- auto file = ProfileUtils::parseJsonFile(QFileInfo(jsonFilePath), false);
- // fix uid
- file->uid = uid;
- // if version is missing, add it from the outside.
- if(file->version.isEmpty())
- {
- file->version = intendedVersion;
- }
- // if this is a dependency (LWJGL), mark it also as volatile
- if(asDependency)
- {
- file->m_volatile = true;
- }
- // insert requirements if needed
- if(!req.uid.isEmpty())
- {
- file->requires.insert(req);
- }
- // insert conflicts if needed
- if(!conflict.uid.isEmpty())
- {
- file->conflicts.insert(conflict);
- }
- // FIXME: @QUALITY do not ignore return value
- ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), jsonFilePath);
- component = new Component(this, uid, file);
- component->m_version = intendedVersion;
- }
- else if(!intendedVersion.isEmpty())
- {
- auto metaVersion = APPLICATION->metadataIndex()->get(uid, intendedVersion);
- component = new Component(this, metaVersion);
- }
- else
- {
- return;
- }
- component->m_dependencyOnly = asDependency;
- component->m_important = !asDependency;
- components.append(component);
- };
- // TODO: insert depends and conflicts here if these are customized files...
- Meta::Require reqLwjgl;
- reqLwjgl.uid = "org.lwjgl";
- reqLwjgl.suggests = "2.9.1";
- Meta::Require conflictLwjgl3;
- conflictLwjgl3.uid = "org.lwjgl3";
- Meta::Require nullReq;
- addBuiltinPatch("org.lwjgl", true, "2.9.1", nullReq, conflictLwjgl3);
- addBuiltinPatch("net.minecraft", false, QString(), reqLwjgl, nullReq);
-
- // first, collect all other file-based patches and load them
- QMap<QString, ComponentPtr> loadedComponents;
- QDir patchesDir(FS::PathCombine(d->m_instance->instanceRoot(),"patches"));
- for (auto info : patchesDir.entryInfoList(QStringList() << "*.json", QDir::Files))
- {
- // parse the file
- qDebug() << "Reading" << info.fileName();
- auto file = ProfileUtils::parseJsonFile(info, true);
-
- // correct missing or wrong uid based on the file name
- QString uid = info.completeBaseName();
-
- // ignore builtins, they've been handled already
- if (uid == "net.minecraft")
- continue;
- if (uid == "org.lwjgl")
- continue;
-
- // handle horrible corner cases
- if(uid.isEmpty())
- {
- // if you have a file named '.json', make it just go away.
- // FIXME: @QUALITY do not ignore return value
- QFile::remove(info.absoluteFilePath());
- continue;
- }
- file->uid = uid;
- // FIXME: @QUALITY do not ignore return value
- ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), info.absoluteFilePath());
-
- auto component = new Component(this, file->uid, file);
- auto version = d->getOldConfigVersion(file->uid);
- if(!version.isEmpty())
- {
- component->m_version = version;
- }
- loadedComponents[file->uid] = component;
- }
- // try to load the other 'hardcoded' patches (forge, liteloader), if they weren't loaded from files
- auto loadSpecial = [&](const QString & uid, int order)
- {
- auto patchVersion = d->getOldConfigVersion(uid);
- if(!patchVersion.isEmpty() && !loadedComponents.contains(uid))
- {
- auto patch = new Component(this, APPLICATION->metadataIndex()->get(uid, patchVersion));
- patch->setOrder(order);
- loadedComponents[uid] = patch;
- }
- };
- loadSpecial("net.minecraftforge", 5);
- loadSpecial("com.mumfrey.liteloader", 10);
-
- // load the old order.json file, if present
- ProfileUtils::PatchOrder userOrder;
- ProfileUtils::readOverrideOrders(FS::PathCombine(d->m_instance->instanceRoot(), "order.json"), userOrder);
-
- // now add all the patches by user sort order
- for (auto uid : userOrder)
- {
- // ignore builtins
- if (uid == "net.minecraft")
- continue;
- if (uid == "org.lwjgl")
- continue;
- // ordering has a patch that is gone?
- if(!loadedComponents.contains(uid))
- {
- continue;
- }
- components.append(loadedComponents.take(uid));
- }
-
- // is there anything left to sort? - this is used when there are leftover components that aren't part of the order.json
- if(!loadedComponents.isEmpty())
- {
- // inserting into multimap by order number as key sorts the patches and detects duplicates
- QMultiMap<int, ComponentPtr> files;
- auto iter = loadedComponents.begin();
- while(iter != loadedComponents.end())
- {
- files.insert((*iter)->getOrder(), *iter);
- iter++;
- }
-
- // then just extract the patches and put them in the list
- for (auto order : files.keys())
- {
- const auto &values = files.values(order);
- for(auto &value: values)
- {
- // TODO: put back the insertion of problem messages here, so the user knows about the id duplication
- components.append(value);
- }
- }
- }
- // new we have a complete list of components...
- return savePackProfile(componentsFilePath(), components);
-}
-
// END: save/load
void PackProfile::appendComponent(ComponentPtr component)
@@ -1169,15 +924,6 @@ std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
return d->m_profile;
}
-void PackProfile::setOldConfigVersion(const QString& uid, const QString& version)
-{
- if(version.isEmpty())
- {
- return;
- }
- d->m_oldConfigVersions[uid] = version;
-}
-
bool PackProfile::setComponentVersion(const QString& uid, const QString& version, bool important)
{
auto iter = d->componentIndex.find(uid);
diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h
index f30deb5a..989d1c6a 100644
--- a/launcher/minecraft/PackProfile.h
+++ b/launcher/minecraft/PackProfile.h
@@ -143,8 +143,6 @@ private:
bool installCustomJar_internal(QString filepath);
bool removeComponent_internal(ComponentPtr patch);
- bool migratePreComponentConfig();
-
private: /* data */
std::unique_ptr<PackProfileData> d;
diff --git a/launcher/minecraft/PackProfile_p.h b/launcher/minecraft/PackProfile_p.h
index fce921bb..715e0460 100644
--- a/launcher/minecraft/PackProfile_p.h
+++ b/launcher/minecraft/PackProfile_p.h
@@ -18,18 +18,6 @@ struct PackProfileData
// the launch profile (volatile, temporary thing created on demand)
std::shared_ptr<LaunchProfile> m_profile;
- // version information migrated from instance.cfg file. Single use on migration!
- std::map<QString, QString> m_oldConfigVersions;
- QString getOldConfigVersion(const QString& uid) const
- {
- const auto iter = m_oldConfigVersions.find(uid);
- if(iter != m_oldConfigVersions.cend())
- {
- return (*iter).second;
- }
- return QString();
- }
-
// persistent list of components and related machinery
ComponentContainer components;
ComponentIndex componentIndex;
diff --git a/launcher/minecraft/legacy/LegacyInstance.cpp b/launcher/minecraft/legacy/LegacyInstance.cpp
deleted file mode 100644
index f467ec06..00000000
--- a/launcher/minecraft/legacy/LegacyInstance.cpp
+++ /dev/null
@@ -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;
-}
diff --git a/launcher/minecraft/legacy/LegacyInstance.h b/launcher/minecraft/legacy/LegacyInstance.h
deleted file mode 100644
index 298543f7..00000000
--- a/launcher/minecraft/legacy/LegacyInstance.h
+++ /dev/null
@@ -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;
-};
diff --git a/launcher/minecraft/legacy/LegacyModList.cpp b/launcher/minecraft/legacy/LegacyModList.cpp
deleted file mode 100644
index e9948ab1..00000000
--- a/launcher/minecraft/legacy/LegacyModList.cpp
+++ /dev/null
@@ -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;
-}
diff --git a/launcher/minecraft/legacy/LegacyModList.h b/launcher/minecraft/legacy/LegacyModList.h
deleted file mode 100644
index fade736e..00000000
--- a/launcher/minecraft/legacy/LegacyModList.h
+++ /dev/null
@@ -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;
-};
diff --git a/launcher/minecraft/legacy/LegacyUpgradeTask.cpp b/launcher/minecraft/legacy/LegacyUpgradeTask.cpp
deleted file mode 100644
index a4ea60cd..00000000
--- a/launcher/minecraft/legacy/LegacyUpgradeTask.cpp
+++ /dev/null
@@ -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;
-}
-
diff --git a/launcher/minecraft/legacy/LegacyUpgradeTask.h b/launcher/minecraft/legacy/LegacyUpgradeTask.h
deleted file mode 100644
index 542e17b8..00000000
--- a/launcher/minecraft/legacy/LegacyUpgradeTask.h
+++ /dev/null
@@ -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;
-};
diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
index 8de5fc9f..9dcb3504 100644
--- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
+++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
@@ -720,8 +720,6 @@ void PackInstallTask::install()
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();
diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
index 1d300192..f655a066 100644
--- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
+++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
@@ -122,8 +122,6 @@ void PackInstallTask::install()
QString instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();
diff --git a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp
index 03570226..33df6fa4 100644
--- a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp
+++ b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp
@@ -181,8 +181,6 @@ void PackInstallTask::install()
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();
diff --git a/launcher/modplatform/technic/TechnicPackProcessor.cpp b/launcher/modplatform/technic/TechnicPackProcessor.cpp
index c45061ac..156a295a 100644
--- a/launcher/modplatform/technic/TechnicPackProcessor.cpp
+++ b/launcher/modplatform/technic/TechnicPackProcessor.cpp
@@ -31,8 +31,6 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, const
QString minecraftPath = FS::PathCombine(stagingPath, ".minecraft");
QString configPath = FS::PathCombine(stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(globalSettings, instanceSettings, stagingPath);
instance.setName(instName);
diff --git a/launcher/ui/dialogs/ModDownloadDialog.cpp b/launcher/ui/dialogs/ModDownloadDialog.cpp
index 6b807b8c..23ca8731 100644
--- a/launcher/ui/dialogs/ModDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ModDownloadDialog.cpp
@@ -5,6 +5,7 @@
#include <InstanceList.h>
#include "ProgressDialog.h"
+#include "CustomMessageBox.h"
#include <QLayout>
#include <QPushButton>
@@ -39,9 +40,10 @@ ModDownloadDialog::ModDownloadDialog(const std::shared_ptr<ModFolderModel> &mods
// Bonk Qt over its stupid head and make sure it understands which button is the default one...
// See: https://stackoverflow.com/questions/24556831/qbuttonbox-set-default-button
auto OkButton = m_buttons->button(QDialogButtonBox::Ok);
+ OkButton->setEnabled(false);
OkButton->setDefault(true);
OkButton->setAutoDefault(true);
- connect(OkButton, &QPushButton::clicked, this, &ModDownloadDialog::accept);
+ connect(OkButton, &QPushButton::clicked, this, &ModDownloadDialog::confirm);
auto CancelButton = m_buttons->button(QDialogButtonBox::Cancel);
CancelButton->setDefault(false);
@@ -52,6 +54,7 @@ ModDownloadDialog::ModDownloadDialog(const std::shared_ptr<ModFolderModel> &mods
HelpButton->setDefault(false);
HelpButton->setAutoDefault(false);
connect(HelpButton, &QPushButton::clicked, m_container, &PageContainer::help);
+
QMetaObject::connectSlotsByName(this);
setWindowModality(Qt::WindowModal);
setWindowTitle("Download mods");
@@ -67,6 +70,36 @@ void ModDownloadDialog::reject()
QDialog::reject();
}
+void ModDownloadDialog::confirm()
+{
+ auto keys = modTask.keys();
+ keys.sort(Qt::CaseInsensitive);
+
+ auto info = QString(tr("You're about to download the following mods:"));
+ info.append("\n\n");
+ for(auto task : keys){
+ info.append(task);
+ info.append("\n --> ");
+ info.append(tr("File name: "));
+ info.append(modTask.find(task).value()->getFilename());
+ info.append('\n');
+ }
+
+ auto confirm_dialog = CustomMessageBox::selectable(
+ this,
+ tr("Confirm mods to download"),
+ info,
+ QMessageBox::NoIcon,
+ QMessageBox::Cancel | QMessageBox::Ok,
+ QMessageBox::Ok
+ );
+
+ auto AcceptButton = confirm_dialog->button(QMessageBox::Ok);
+ connect(AcceptButton, &QPushButton::clicked, this, &ModDownloadDialog::accept);
+
+ confirm_dialog->open();
+}
+
void ModDownloadDialog::accept()
{
QDialog::accept();
@@ -83,16 +116,35 @@ QList<BasePage *> ModDownloadDialog::getPages()
};
}
-void ModDownloadDialog::setSuggestedMod(const QString& name, ModDownloadTask* task)
+void ModDownloadDialog::addSelectedMod(const QString& name, ModDownloadTask* task)
+{
+ removeSelectedMod(name);
+ modTask.insert(name, task);
+
+ m_buttons->button(QDialogButtonBox::Ok)->setEnabled(!modTask.isEmpty());
+}
+
+void ModDownloadDialog::removeSelectedMod(const QString &name)
+{
+ if(modTask.contains(name))
+ delete modTask.find(name).value();
+ modTask.remove(name);
+
+ m_buttons->button(QDialogButtonBox::Ok)->setEnabled(!modTask.isEmpty());
+}
+
+bool ModDownloadDialog::isModSelected(const QString &name, const QString& filename) const
{
- modTask.reset(task);
- m_buttons->button(QDialogButtonBox::Ok)->setEnabled(task);
+ // FIXME: Is there a way to check for versions without checking the filename
+ // as a heuristic, other than adding such info to ModDownloadTask itself?
+ auto iter = modTask.find(name);
+ return iter != modTask.end() && (iter.value()->getFilename() == filename);
}
ModDownloadDialog::~ModDownloadDialog()
{
}
-ModDownloadTask *ModDownloadDialog::getTask() {
- return modTask.release();
+const QList<ModDownloadTask*> ModDownloadDialog::getTasks() {
+ return modTask.values();
}
diff --git a/launcher/ui/dialogs/ModDownloadDialog.h b/launcher/ui/dialogs/ModDownloadDialog.h
index ece8e328..309d89d0 100644
--- a/launcher/ui/dialogs/ModDownloadDialog.h
+++ b/launcher/ui/dialogs/ModDownloadDialog.h
@@ -29,12 +29,15 @@ public:
QString dialogTitle() override;
QList<BasePage *> getPages() override;
- void setSuggestedMod(const QString & name = QString(), ModDownloadTask * task = nullptr);
+ void addSelectedMod(const QString & name = QString(), ModDownloadTask * task = nullptr);
+ void removeSelectedMod(const QString & name = QString());
+ bool isModSelected(const QString & name, const QString & filename) const;
- ModDownloadTask * getTask();
+ const QList<ModDownloadTask*> getTasks();
const std::shared_ptr<ModFolderModel> &mods;
public slots:
+ void confirm();
void accept() override;
void reject() override;
@@ -49,6 +52,6 @@ private:
ModrinthPage *modrinthPage = nullptr;
FlameModPage *flameModPage = nullptr;
- std::unique_ptr<ModDownloadTask> modTask;
+ QHash<QString, ModDownloadTask*> modTask;
BaseInstance *m_instance;
};
diff --git a/launcher/ui/pages/instance/LegacyUpgradePage.cpp b/launcher/ui/pages/instance/LegacyUpgradePage.cpp
deleted file mode 100644
index cb78af02..00000000
--- a/launcher/ui/pages/instance/LegacyUpgradePage.cpp
+++ /dev/null
@@ -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();
-}
diff --git a/launcher/ui/pages/instance/LegacyUpgradePage.h b/launcher/ui/pages/instance/LegacyUpgradePage.h
deleted file mode 100644
index 7c51956b..00000000
--- a/launcher/ui/pages/instance/LegacyUpgradePage.h
+++ /dev/null
@@ -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;
-};
diff --git a/launcher/ui/pages/instance/LegacyUpgradePage.ui b/launcher/ui/pages/instance/LegacyUpgradePage.ui
deleted file mode 100644
index b22c03e5..00000000
--- a/launcher/ui/pages/instance/LegacyUpgradePage.ui
+++ /dev/null
@@ -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>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;h1 style=&quot; margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:xx-large; font-weight:600;&quot;&gt;Upgrade is required&lt;/span&gt;&lt;/h1&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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.&lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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.&lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Please report any issues on our &lt;a href=&quot;https://github.com/PolyMC/PolyMC/issues&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#3584e4;&quot;&gt;github issues page&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>
diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp
index 494d32f0..b342accf 100644
--- a/launcher/ui/pages/instance/ModFolderPage.cpp
+++ b/launcher/ui/pages/instance/ModFolderPage.cpp
@@ -365,8 +365,7 @@ void ModFolderPage::on_actionInstall_mods_triggered()
}
ModDownloadDialog mdownload(m_mods, this, m_inst);
if(mdownload.exec()) {
- ModDownloadTask *task = mdownload.getTask();
- if (task) {
+ for(auto task : mdownload.getTasks()){
connect(task, &Task::failed, [this, task](QString reason) {
task->deleteLater();
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show();
diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp
index a816c681..6d33a6ac 100644
--- a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp
@@ -4,193 +4,211 @@
#include <QKeyEvent>
#include "Application.h"
-#include "Json.h"
-#include "ui/dialogs/ModDownloadDialog.h"
-#include "InstanceImportTask.h"
#include "FlameModModel.h"
+#include "InstanceImportTask.h"
+#include "Json.h"
#include "ModDownloadTask.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
+#include "ui/dialogs/ModDownloadDialog.h"
FlameModPage::FlameModPage(ModDownloadDialog *dialog, BaseInstance *instance)
- : QWidget(dialog), m_instance(instance), ui(new Ui::FlameModPage), dialog(dialog)
-{
- ui->setupUi(this);
- connect(ui->searchButton, &QPushButton::clicked, this, &FlameModPage::triggerSearch);
- ui->searchEdit->installEventFilter(this);
- listModel = new FlameMod::ListModel(this);
- ui->packView->setModel(listModel);
-
- ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
-
- // index is used to set the sorting with the flame api
- ui->sortByBox->addItem(tr("Sort by Featured"));
- ui->sortByBox->addItem(tr("Sort by Popularity"));
- ui->sortByBox->addItem(tr("Sort by last updated"));
- ui->sortByBox->addItem(tr("Sort by Name"));
- ui->sortByBox->addItem(tr("Sort by Author"));
- ui->sortByBox->addItem(tr("Sort by Downloads"));
-
- connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch()));
- connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameModPage::onSelectionChanged);
- connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameModPage::onVersionSelectionChanged);
+ : QWidget(dialog), m_instance(instance), ui(new Ui::FlameModPage),
+ dialog(dialog) {
+ ui->setupUi(this);
+ connect(ui->searchButton, &QPushButton::clicked, this,
+ &FlameModPage::triggerSearch);
+ ui->searchEdit->installEventFilter(this);
+ listModel = new FlameMod::ListModel(this);
+ ui->packView->setModel(listModel);
+
+ ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(
+ Qt::ScrollBarAsNeeded);
+ ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
+
+ // index is used to set the sorting with the flame api
+ ui->sortByBox->addItem(tr("Sort by Featured"));
+ ui->sortByBox->addItem(tr("Sort by Popularity"));
+ ui->sortByBox->addItem(tr("Sort by last updated"));
+ ui->sortByBox->addItem(tr("Sort by Name"));
+ ui->sortByBox->addItem(tr("Sort by Author"));
+ ui->sortByBox->addItem(tr("Sort by Downloads"));
+
+ connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(triggerSearch()));
+ connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged,
+ this, &FlameModPage::onSelectionChanged);
+ connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this,
+ &FlameModPage::onVersionSelectionChanged);
+ connect(ui->modSelectionButton, &QPushButton::clicked, this,
+ &FlameModPage::onModSelected);
}
-FlameModPage::~FlameModPage()
-{
- delete ui;
-}
+FlameModPage::~FlameModPage() { delete ui; }
-bool FlameModPage::eventFilter(QObject* watched, QEvent* event)
-{
- if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
- QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
- if (keyEvent->key() == Qt::Key_Return) {
- triggerSearch();
- keyEvent->accept();
- return true;
- }
+bool FlameModPage::eventFilter(QObject *watched, QEvent *event) {
+ if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
+ if (keyEvent->key() == Qt::Key_Return) {
+ triggerSearch();
+ keyEvent->accept();
+ return true;
}
- return QWidget::eventFilter(watched, event);
+ }
+ return QWidget::eventFilter(watched, event);
}
-bool FlameModPage::shouldDisplay() const
-{
- return true;
-}
+bool FlameModPage::shouldDisplay() const { return true; }
-void FlameModPage::openedImpl()
-{
- suggestCurrent();
- triggerSearch();
+void FlameModPage::openedImpl() {
+ updateSelectionButton();
+ triggerSearch();
}
-void FlameModPage::triggerSearch()
-{
- listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex());
+void FlameModPage::triggerSearch() {
+ listModel->searchWithTerm(ui->searchEdit->text(),
+ ui->sortByBox->currentIndex());
}
-void FlameModPage::onSelectionChanged(QModelIndex first, QModelIndex second)
-{
- ui->versionSelectionBox->clear();
-
- if(!first.isValid())
- {
- if(isOpened)
- {
- dialog->setSuggestedMod();
- }
- return;
+void FlameModPage::onSelectionChanged(QModelIndex first, QModelIndex second) {
+ ui->versionSelectionBox->clear();
+
+ if (!first.isValid()) {
+ return;
+ }
+
+ current = listModel->data(first, Qt::UserRole).value<FlameMod::IndexedPack>();
+ QString text = "";
+ QString name = current.name;
+
+ if (current.websiteUrl.isEmpty())
+ text = name;
+ else
+ text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
+ if (!current.authors.empty()) {
+ auto authorToStr = [](FlameMod::ModpackAuthor &author) {
+ if (author.url.isEmpty()) {
+ return author.name;
+ }
+ return QString("<a href=\"%1\">%2</a>").arg(author.url, author.name);
+ };
+ QStringList authorStrs;
+ for (auto &author : current.authors) {
+ authorStrs.push_back(authorToStr(author));
}
-
- current = listModel->data(first, Qt::UserRole).value<FlameMod::IndexedPack>();
- QString text = "";
- QString name = current.name;
-
- if (current.websiteUrl.isEmpty())
- text = name;
- else
- text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
- if (!current.authors.empty()) {
- auto authorToStr = [](FlameMod::ModpackAuthor & author) {
- if(author.url.isEmpty()) {
- return author.name;
- }
- return QString("<a href=\"%1\">%2</a>").arg(author.url, author.name);
- };
- QStringList authorStrs;
- for(auto & author: current.authors) {
- authorStrs.push_back(authorToStr(author));
+ text += "<br>" + tr(" by ") + authorStrs.join(", ");
+ }
+ text += "<br><br>";
+
+ ui->packDescription->setHtml(text + current.description);
+
+ if (!current.versionsLoaded) {
+ qDebug() << "Loading flame mod versions";
+
+ ui->modSelectionButton->setText(tr("Loading versions..."));
+ ui->modSelectionButton->setEnabled(false);
+
+ auto netJob =
+ new NetJob(QString("Flame::ModVersions(%1)").arg(current.name),
+ APPLICATION->network());
+ auto response = new QByteArray();
+ int addonId = current.addonId;
+ netJob->addNetAction(Net::Download::makeByteArray(
+ QString("https://addons-ecs.forgesvc.net/api/v2/addon/%1/files")
+ .arg(addonId),
+ response));
+
+ QObject::connect(netJob, &NetJob::succeeded, this, [this, response] {
+ QJsonParseError parse_error;
+ QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
+ if (parse_error.error != QJsonParseError::NoError) {
+ qWarning() << "Error while parsing JSON response from Flame at "
+ << parse_error.offset
+ << " reason: " << parse_error.errorString();
+ qWarning() << *response;
+ return;
+ }
+ QJsonArray arr = doc.array();
+ try {
+ FlameMod::loadIndexedPackVersions(current, arr, APPLICATION->network(),
+ m_instance);
+ } catch (const JSONValidationError &e) {
+ qDebug() << *response;
+ qWarning() << "Error while reading Flame mod version: " << e.cause();
+ }
+ auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
+ QString mcVersion = packProfile->getComponentVersion("net.minecraft");
+ QString loaderString =
+ (packProfile->getComponentVersion("net.minecraftforge").isEmpty())
+ ? "fabric"
+ : "forge";
+ for (int i = 0; i < current.versions.size(); i++) {
+ auto version = current.versions[i];
+ if (!version.mcVersion.contains(mcVersion)) {
+ continue;
}
- text += "<br>" + tr(" by ") + authorStrs.join(", ");
- }
- text += "<br><br>";
-
- ui->packDescription->setHtml(text + current.description);
-
- if (!current.versionsLoaded)
- {
- qDebug() << "Loading flame mod versions";
- auto netJob = new NetJob(QString("Flame::ModVersions(%1)").arg(current.name), APPLICATION->network());
- std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
- int addonId = current.addonId;
- netJob->addNetAction(Net::Download::makeByteArray(QString("https://addons-ecs.forgesvc.net/api/v2/addon/%1/files").arg(addonId), response.get()));
-
- QObject::connect(netJob, &NetJob::succeeded, this, [this, response, netJob]
- {
- netJob->deleteLater();
- QJsonParseError parse_error;
- QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
- if(parse_error.error != QJsonParseError::NoError) {
- qWarning() << "Error while parsing JSON response from Flame at " << parse_error.offset << " reason: " << parse_error.errorString();
- qWarning() << *response;
- return;
- }
- QJsonArray arr = doc.array();
- try
- {
- FlameMod::loadIndexedPackVersions(current, arr, APPLICATION->network(), m_instance);
- }
- catch(const JSONValidationError &e)
- {
- qDebug() << *response;
- qWarning() << "Error while reading Flame mod version: " << e.cause();
- }
- auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
- QString mcVersion = packProfile->getComponentVersion("net.minecraft");
- QString loaderString = (packProfile->getComponentVersion("net.minecraftforge").isEmpty()) ? "fabric" : "forge";
- for(int i = 0; i < current.versions.size(); i++) {
- auto version = current.versions[i];
- if(!version.mcVersion.contains(mcVersion)){
- continue;
- }
- ui->versionSelectionBox->addItem(version.version, QVariant(i));
- }
- if(ui->versionSelectionBox->count() == 0){
- ui->versionSelectionBox->addItem(tr("No Valid Version found!"), QVariant(-1));
- }
-
- suggestCurrent();
- });
- netJob->start();
+ ui->versionSelectionBox->addItem(version.version, QVariant(i));
+ }
+ if (ui->versionSelectionBox->count() == 0) {
+ ui->versionSelectionBox->addItem(tr("No Valid Version found!"),
+ QVariant(-1));
+ }
+
+ ui->modSelectionButton->setText(tr("Cannot select invalid version :("));
+ updateSelectionButton();
+ });
+ QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
+ netJob->deleteLater();
+ delete response;
+ });
+ netJob->start();
+ } else {
+ for (int i = 0; i < current.versions.size(); i++) {
+ ui->versionSelectionBox->addItem(current.versions[i].version,
+ QVariant(i));
}
- else
- {
- for(int i = 0; i < current.versions.size(); i++) {
- ui->versionSelectionBox->addItem(current.versions[i].version, QVariant(i));
- }
- if(ui->versionSelectionBox->count() == 0){
- ui->versionSelectionBox->addItem(tr("No Valid Version found!"), QVariant(-1));
- }
- suggestCurrent();
+ if (ui->versionSelectionBox->count() == 0) {
+ ui->versionSelectionBox->addItem(tr("No Valid Version found!"),
+ QVariant(-1));
}
-}
-void FlameModPage::suggestCurrent()
-{
- if(!isOpened)
- {
- return;
- }
+ updateSelectionButton();
+ }
+}
- if (selectedVersion == -1)
- {
- dialog->setSuggestedMod();
- return;
- }
+void FlameModPage::updateSelectionButton() {
+ if (!isOpened || selectedVersion < 0) {
+ ui->modSelectionButton->setEnabled(false);
+ return;
+ }
+
+ ui->modSelectionButton->setEnabled(true);
+ auto &version = current.versions[selectedVersion];
+ if (!dialog->isModSelected(current.name, version.fileName)) {
+ ui->modSelectionButton->setText(tr("Select mod for download"));
+ } else {
+ ui->modSelectionButton->setText(tr("Deselect mod for download"));
+ }
+}
- auto version = current.versions[selectedVersion];
- dialog->setSuggestedMod(current.name, new ModDownloadTask(version.downloadUrl, version.fileName , dialog->mods));
+void FlameModPage::onVersionSelectionChanged(QString data) {
+ if (data.isNull() || data.isEmpty()) {
+ selectedVersion = -1;
+ return;
+ }
+ selectedVersion = ui->versionSelectionBox->currentData().toInt();
+ updateSelectionButton();
}
-void FlameModPage::onVersionSelectionChanged(QString data)
-{
- if(data.isNull() || data.isEmpty())
- {
- selectedVersion = -1;
- return;
- }
- selectedVersion = ui->versionSelectionBox->currentData().toInt();
- suggestCurrent();
+void FlameModPage::onModSelected() {
+ auto &version = current.versions[selectedVersion];
+ if (dialog->isModSelected(current.name, version.fileName)) {
+ dialog->removeSelectedMod(current.name);
+ } else {
+ dialog->addSelectedMod(current.name,
+ new ModDownloadTask(version.downloadUrl,
+ version.fileName, dialog->mods));
+ }
+
+ updateSelectionButton();
}
diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.h b/launcher/ui/pages/modplatform/flame/FlameModPage.h
index 8fa3248a..b5b19a4f 100644
--- a/launcher/ui/pages/modplatform/flame/FlameModPage.h
+++ b/launcher/ui/pages/modplatform/flame/FlameModPage.h
@@ -50,12 +50,13 @@ public:
BaseInstance *m_instance;
private:
- void suggestCurrent();
+ void updateSelectionButton();
private slots:
void triggerSearch();
void onSelectionChanged(QModelIndex first, QModelIndex second);
void onVersionSelectionChanged(QString data);
+ void onModSelected();
private:
Ui::FlameModPage *ui = nullptr;
diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.ui b/launcher/ui/pages/modplatform/flame/FlameModPage.ui
index 7da0bb4a..36df7e8a 100644
--- a/launcher/ui/pages/modplatform/flame/FlameModPage.ui
+++ b/launcher/ui/pages/modplatform/flame/FlameModPage.ui
@@ -1,90 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>FlameModPage</class>
- <widget class="QWidget" name="FlameModPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>837</width>
- <height>685</height>
- </rect>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="0" colspan="2">
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="1" column="0">
- <widget class="QListView" name="packView">
- <property name="iconSize">
- <size>
- <width>48</width>
- <height>48</height>
- </size>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOff</enum>
- </property>
- <property name="alternatingRowColors">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QTextBrowser" name="packDescription">
- <property name="openExternalLinks">
- <bool>true</bool>
- </property>
- <property name="openLinks">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="2" column="0" colspan="2">
- <layout class="QGridLayout" name="gridLayout_4" columnstretch="0,0,0" rowminimumheight="0" columnminimumwidth="0,0,0">
- <item row="0" column="2">
- <widget class="QComboBox" name="versionSelectionBox"/>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Version selected:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QComboBox" name="sortByBox"/>
- </item>
- </layout>
- </item>
- <item row="0" column="1">
- <widget class="QPushButton" name="searchButton">
- <property name="text">
- <string>Search</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLineEdit" name="searchEdit">
- <property name="placeholderText">
- <string>Search and filter ...</string>
- </property>
- </widget>
- </item>
+ <class>FlameModPage</class>
+ <widget class="QWidget" name="FlameModPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>837</width>
+ <height>685</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="0" colspan="2">
+ <layout class="QGridLayout" name="gridLayout_4" columnstretch="0,0,0" rowminimumheight="0,0,0" columnminimumwidth="0,0,0">
+ <item row="1" column="2">
+ <widget class="QComboBox" name="versionSelectionBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QComboBox" name="sortByBox"/>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Version selected:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="modSelectionButton">
+ <property name="text">
+ <string>Select mod for download</string>
+ </property>
+ </widget>
+ </item>
</layout>
- </widget>
- <tabstops>
- <tabstop>searchEdit</tabstop>
- <tabstop>searchButton</tabstop>
- <tabstop>packView</tabstop>
- <tabstop>packDescription</tabstop>
- <tabstop>sortByBox</tabstop>
- <tabstop>versionSelectionBox</tabstop>
- </tabstops>
- <resources/>
- <connections/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLineEdit" name="searchEdit">
+ <property name="placeholderText">
+ <string>Search and filter ...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="1" column="0">
+ <widget class="QListView" name="packView">
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>48</width>
+ <height>48</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QTextBrowser" name="packDescription">
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ <property name="openLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="1">
+ <widget class="QPushButton" name="searchButton">
+ <property name="text">
+ <string>Search</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>searchEdit</tabstop>
+ <tabstop>searchButton</tabstop>
+ <tabstop>packView</tabstop>
+ <tabstop>packDescription</tabstop>
+ <tabstop>sortByBox</tabstop>
+ <tabstop>versionSelectionBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
</ui>
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp
index c5a54c29..fc6aff96 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp
@@ -4,177 +4,199 @@
#include <QKeyEvent>
#include "Application.h"
-#include "Json.h"
-#include "ui/dialogs/ModDownloadDialog.h"
#include "InstanceImportTask.h"
-#include "ModrinthModel.h"
+#include "Json.h"
#include "ModDownloadTask.h"
+#include "ModrinthModel.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
+#include "ui/dialogs/ModDownloadDialog.h"
ModrinthPage::ModrinthPage(ModDownloadDialog *dialog, BaseInstance *instance)
- : QWidget(dialog), m_instance(instance), ui(new Ui::ModrinthPage), dialog(dialog)
-{
- ui->setupUi(this);
- connect(ui->searchButton, &QPushButton::clicked, this, &ModrinthPage::triggerSearch);
- ui->searchEdit->installEventFilter(this);
- listModel = new Modrinth::ListModel(this);
- ui->packView->setModel(listModel);
-
- ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
-
- // index is used to set the sorting with the modrinth api
- ui->sortByBox->addItem(tr("Sort by Relevence"));
- ui->sortByBox->addItem(tr("Sort by Downloads"));
- ui->sortByBox->addItem(tr("Sort by Follows"));
- ui->sortByBox->addItem(tr("Sort by last updated"));
- ui->sortByBox->addItem(tr("Sort by newest"));
-
- connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch()));
- connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthPage::onSelectionChanged);
- connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthPage::onVersionSelectionChanged);
+ : QWidget(dialog), m_instance(instance), ui(new Ui::ModrinthPage),
+ dialog(dialog) {
+ ui->setupUi(this);
+ connect(ui->searchButton, &QPushButton::clicked, this,
+ &ModrinthPage::triggerSearch);
+ ui->searchEdit->installEventFilter(this);
+ listModel = new Modrinth::ListModel(this);
+ ui->packView->setModel(listModel);
+
+ ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(
+ Qt::ScrollBarAsNeeded);
+ ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
+
+ // index is used to set the sorting with the modrinth api
+ ui->sortByBox->addItem(tr("Sort by Relevence"));
+ ui->sortByBox->addItem(tr("Sort by Downloads"));
+ ui->sortByBox->addItem(tr("Sort by Follows"));
+ ui->sortByBox->addItem(tr("Sort by last updated"));
+ ui->sortByBox->addItem(tr("Sort by newest"));
+
+ connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(triggerSearch()));
+ connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged,
+ this, &ModrinthPage::onSelectionChanged);
+ connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this,
+ &ModrinthPage::onVersionSelectionChanged);
+ connect(ui->modSelectionButton, &QPushButton::clicked, this,
+ &ModrinthPage::onModSelected);
}
-ModrinthPage::~ModrinthPage()
-{
- delete ui;
-}
+ModrinthPage::~ModrinthPage() { delete ui; }
-bool ModrinthPage::eventFilter(QObject* watched, QEvent* event)
-{
- if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
- QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
- if (keyEvent->key() == Qt::Key_Return) {
- triggerSearch();
- keyEvent->accept();
- return true;
- }
+bool ModrinthPage::eventFilter(QObject *watched, QEvent *event) {
+ if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
+ if (keyEvent->key() == Qt::Key_Return) {
+ triggerSearch();
+ keyEvent->accept();
+ return true;
}
- return QWidget::eventFilter(watched, event);
+ }
+ return QWidget::eventFilter(watched, event);
}
-bool ModrinthPage::shouldDisplay() const
-{
- return true;
-}
+bool ModrinthPage::shouldDisplay() const { return true; }
-void ModrinthPage::openedImpl()
-{
- suggestCurrent();
- triggerSearch();
+void ModrinthPage::openedImpl() {
+ updateSelectionButton();
+ triggerSearch();
}
-void ModrinthPage::triggerSearch()
-{
- listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex());
+void ModrinthPage::triggerSearch() {
+ listModel->searchWithTerm(ui->searchEdit->text(),
+ ui->sortByBox->currentIndex());
}
-void ModrinthPage::onSelectionChanged(QModelIndex first, QModelIndex second)
-{
- ui->versionSelectionBox->clear();
-
- if(!first.isValid())
- {
- if(isOpened)
- {
- dialog->setSuggestedMod();
- }
+void ModrinthPage::onSelectionChanged(QModelIndex first, QModelIndex second) {
+ ui->versionSelectionBox->clear();
+
+ if (!first.isValid()) {
+ return;
+ }
+
+ current = listModel->data(first, Qt::UserRole).value<Modrinth::IndexedPack>();
+ QString text = "";
+ QString name = current.name;
+
+ if (current.websiteUrl.isEmpty())
+ text = name;
+ else
+ text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
+ text += "<br>" + tr(" by ") + "<a href=\"" + current.author.url + "\">" +
+ current.author.name + "</a><br><br>";
+ ui->packDescription->setHtml(text + current.description);
+
+ if (!current.versionsLoaded) {
+ qDebug() << "Loading Modrinth mod versions";
+
+ ui->modSelectionButton->setText(tr("Loading versions..."));
+ ui->modSelectionButton->setEnabled(false);
+
+ auto netJob =
+ new NetJob(QString("Modrinth::ModVersions(%1)").arg(current.name),
+ APPLICATION->network());
+ auto response = new QByteArray();
+ QString addonId = current.addonId;
+ netJob->addNetAction(Net::Download::makeByteArray(
+ QString("https://api.modrinth.com/v2/project/%1/version").arg(addonId),
+ response));
+
+ QObject::connect(netJob, &NetJob::succeeded, this, [this, response] {
+ QJsonParseError parse_error;
+ QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
+ if (parse_error.error != QJsonParseError::NoError) {
+ qWarning() << "Error while parsing JSON response from Modrinth at "
+ << parse_error.offset
+ << " reason: " << parse_error.errorString();
+ qWarning() << *response;
return;
- }
-
- current = listModel->data(first, Qt::UserRole).value<Modrinth::IndexedPack>();
- QString text = "";
- QString name = current.name;
-
- if (current.websiteUrl.isEmpty())
- text = name;
- else
- text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
- text += "<br>"+ tr(" by ") + "<a href=\""+current.author.url+"\">"+current.author.name+"</a><br><br>";
- ui->packDescription->setHtml(text + current.description);
-
- if (!current.versionsLoaded)
- {
- qDebug() << "Loading Modrinth mod versions";
- auto netJob = new NetJob(QString("Modrinth::ModVersions(%1)").arg(current.name), APPLICATION->network());
- std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
- QString addonId = current.addonId;
- netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.modrinth.com/v2/project/%1/version").arg(addonId), response.get()));
-
- QObject::connect(netJob, &NetJob::succeeded, this, [this, response, netJob]
- {
- netJob->deleteLater();
- QJsonParseError parse_error;
- QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
- if(parse_error.error != QJsonParseError::NoError) {
- qWarning() << "Error while parsing JSON response from Modrinth at " << parse_error.offset << " reason: " << parse_error.errorString();
- qWarning() << *response;
- return;
- }
- QJsonArray arr = doc.array();
- try
- {
- Modrinth::loadIndexedPackVersions(current, arr, APPLICATION->network(), m_instance);
- }
- catch(const JSONValidationError &e)
- {
- qDebug() << *response;
- qWarning() << "Error while reading Modrinth mod version: " << e.cause();
- }
- auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
- QString mcVersion = packProfile->getComponentVersion("net.minecraft");
- QString loaderString = (packProfile->getComponentVersion("net.minecraftforge").isEmpty()) ? "fabric" : "forge";
- for(int i = 0; i < current.versions.size(); i++) {
- auto version = current.versions[i];
- if(!version.mcVersion.contains(mcVersion) || !version.loaders.contains(loaderString)){
- continue;
- }
- ui->versionSelectionBox->addItem(version.version, QVariant(i));
- }
- if(ui->versionSelectionBox->count() == 0){
- ui->versionSelectionBox->addItem(tr("No Valid Version found !"), QVariant(-1));
- }
-
- suggestCurrent();
- });
- netJob->start();
- }
- else
- {
- for(int i = 0; i < current.versions.size(); i++) {
- ui->versionSelectionBox->addItem(current.versions[i].version, QVariant(i));
- }
- if(ui->versionSelectionBox->count() == 0){
- ui->versionSelectionBox->addItem(tr("No Valid Version found !"), QVariant(-1));
+ }
+ QJsonArray arr = doc.array();
+ try {
+ Modrinth::loadIndexedPackVersions(current, arr, APPLICATION->network(),
+ m_instance);
+ } catch (const JSONValidationError &e) {
+ qDebug() << *response;
+ qWarning() << "Error while reading Modrinth mod version: " << e.cause();
+ }
+ auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
+ QString mcVersion = packProfile->getComponentVersion("net.minecraft");
+ QString loaderString =
+ (packProfile->getComponentVersion("net.minecraftforge").isEmpty())
+ ? "fabric"
+ : "forge";
+ for (int i = 0; i < current.versions.size(); i++) {
+ auto version = current.versions[i];
+ if (!version.mcVersion.contains(mcVersion) ||
+ !version.loaders.contains(loaderString)) {
+ continue;
}
- suggestCurrent();
+ ui->versionSelectionBox->addItem(version.version, QVariant(i));
+ }
+ if (ui->versionSelectionBox->count() == 0) {
+ ui->versionSelectionBox->addItem(tr("No Valid Version found !"),
+ QVariant(-1));
+ }
+
+ ui->modSelectionButton->setText(tr("Cannot select invalid version :("));
+ updateSelectionButton();
+ });
+
+ QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
+ netJob->deleteLater();
+ delete response;
+ });
+
+ netJob->start();
+ } else {
+ for (int i = 0; i < current.versions.size(); i++) {
+ ui->versionSelectionBox->addItem(current.versions[i].version,
+ QVariant(i));
}
+ if (ui->versionSelectionBox->count() == 0) {
+ ui->versionSelectionBox->addItem(tr("No Valid Version found !"),
+ QVariant(-1));
+ }
+
+ updateSelectionButton();
+ }
}
-void ModrinthPage::suggestCurrent()
-{
- if(!isOpened)
- {
- return;
- }
+void ModrinthPage::updateSelectionButton() {
+ if (!isOpened || selectedVersion < 0) {
+ ui->modSelectionButton->setEnabled(false);
+ return;
+ }
+
+ ui->modSelectionButton->setEnabled(true);
+ auto &version = current.versions[selectedVersion];
+ if (!dialog->isModSelected(current.name, version.fileName)) {
+ ui->modSelectionButton->setText(tr("Select mod for download"));
+ } else {
+ ui->modSelectionButton->setText(tr("Deselect mod for download"));
+ }
+}
- if (selectedVersion == -1)
- {
- dialog->setSuggestedMod();
- return;
- }
- auto version = current.versions[selectedVersion];
- dialog->setSuggestedMod(current.name, new ModDownloadTask(version.downloadUrl, version.fileName , dialog->mods));
+void ModrinthPage::onVersionSelectionChanged(QString data) {
+ if (data.isNull() || data.isEmpty()) {
+ selectedVersion = -1;
+ return;
+ }
+ selectedVersion = ui->versionSelectionBox->currentData().toInt();
+ updateSelectionButton();
}
-void ModrinthPage::onVersionSelectionChanged(QString data)
-{
- if(data.isNull() || data.isEmpty())
- {
- selectedVersion = -1;
- return;
- }
- selectedVersion = ui->versionSelectionBox->currentData().toInt();
- suggestCurrent();
+void ModrinthPage::onModSelected() {
+ auto &version = current.versions[selectedVersion];
+ if (dialog->isModSelected(current.name, version.fileName)) {
+ dialog->removeSelectedMod(current.name);
+ } else {
+ dialog->addSelectedMod(current.name,
+ new ModDownloadTask(version.downloadUrl,
+ version.fileName, dialog->mods));
+ }
+
+ updateSelectionButton();
}
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h
index 3c517069..52b538e3 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h
@@ -50,12 +50,13 @@ public:
BaseInstance *m_instance;
private:
- void suggestCurrent();
+ void updateSelectionButton();
private slots:
void triggerSearch();
void onSelectionChanged(QModelIndex first, QModelIndex second);
void onVersionSelectionChanged(QString data);
+ void onModSelected();
private:
Ui::ModrinthPage *ui = nullptr;
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui
index 6d183de5..d0a8b8f7 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui
@@ -1,90 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>ModrinthPage</class>
- <widget class="QWidget" name="ModrinthPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>837</width>
- <height>685</height>
- </rect>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="0" colspan="2">
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="1" column="0">
- <widget class="QListView" name="packView">
- <property name="iconSize">
- <size>
- <width>48</width>
- <height>48</height>
- </size>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOff</enum>
- </property>
- <property name="alternatingRowColors">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QTextBrowser" name="packDescription">
- <property name="openExternalLinks">
- <bool>true</bool>
- </property>
- <property name="openLinks">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="2" column="0" colspan="2">
- <layout class="QGridLayout" name="gridLayout_4" columnstretch="0,0,0" rowminimumheight="0" columnminimumwidth="0,0,0">
- <item row="0" column="2">
- <widget class="QComboBox" name="versionSelectionBox"/>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Version selected:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QComboBox" name="sortByBox"/>
- </item>
- </layout>
- </item>
- <item row="0" column="1">
- <widget class="QPushButton" name="searchButton">
- <property name="text">
- <string>Search</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLineEdit" name="searchEdit">
- <property name="placeholderText">
- <string>Search and filter ...</string>
- </property>
- </widget>
- </item>
+ <class>ModrinthPage</class>
+ <widget class="QWidget" name="ModrinthPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>837</width>
+ <height>685</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="0" colspan="2">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="1" column="2">
+ <widget class="QTextBrowser" name="packDescription">
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ <property name="openLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QListView" name="packView">
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>48</width>
+ <height>48</height>
+ </size>
+ </property>
+ </widget>
+ </item>
</layout>
- </widget>
- <tabstops>
- <tabstop>searchEdit</tabstop>
- <tabstop>searchButton</tabstop>
- <tabstop>packView</tabstop>
- <tabstop>packDescription</tabstop>
- <tabstop>sortByBox</tabstop>
- <tabstop>versionSelectionBox</tabstop>
- </tabstops>
- <resources/>
- <connections/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QPushButton" name="searchButton">
+ <property name="text">
+ <string>Search</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLineEdit" name="searchEdit">
+ <property name="placeholderText">
+ <string>Search and filter ...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <layout class="QGridLayout" name="gridLayout_4" columnstretch="0,0,0,0">
+ <item row="0" column="2">
+ <widget class="QComboBox" name="versionSelectionBox"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Version selected:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QComboBox" name="sortByBox"/>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="modSelectionButton">
+ <property name="text">
+ <string>Select mod for download</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>searchEdit</tabstop>
+ <tabstop>searchButton</tabstop>
+ <tabstop>packView</tabstop>
+ <tabstop>packDescription</tabstop>
+ <tabstop>sortByBox</tabstop>
+ <tabstop>versionSelectionBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
</ui>