From 214d615d185f0544b851d56e6bde4b40adfdcd0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 30 May 2022 01:38:19 +0200 Subject: [PATCH] NOISSUE significantly more reliable detection of modloaders for FTBA --- .../ui/pages/modplatform/import_ftb/Model.cpp | 109 ++++++++++++++++-- .../ui/pages/modplatform/import_ftb/Model.h | 19 ++- .../import_ftb/PackInstallTask.cpp | 25 ++-- 3 files changed, 135 insertions(+), 18 deletions(-) diff --git a/launcher/ui/pages/modplatform/import_ftb/Model.cpp b/launcher/ui/pages/modplatform/import_ftb/Model.cpp index 93671a86..5bb6e5b1 100644 --- a/launcher/ui/pages/modplatform/import_ftb/Model.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/Model.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #if defined(Q_OS_WIN32) #include @@ -71,26 +72,34 @@ QVariant Model::data(const QModelIndex &index, int role) const namespace { #if defined (Q_OS_OSX) -QString getFTBASettingsPath() { - return FS::PathCombine(QDir::homePath(), "Library/Application Support/.ftba/bin/settings.json"); +QString getFTBAPath() { + return FS::PathCombine(QDir::homePath(), "Library/Application Support/.ftba"); } #elif defined(Q_OS_WIN32) -QString getFTBASettingsPath() { +QString getFTBAPath() { wchar_t buf[BUFFER_SIZE]; if(!GetEnvironmentVariableW(L"LOCALAPPDATA", buf, BUFFER_SIZE)) { return QString(); } QString appDataLocal = QString::fromWCharArray(buf); - QString settingsPath = FS::PathCombine(appDataLocal, ".ftba/bin/settings.json"); + QString settingsPath = FS::PathCombine(appDataLocal, ".ftba"); return settingsPath; } #else -QString getFTBASettingsPath() { - return FS::PathCombine(QDir::homePath(), ".ftba/bin/settings.json"); +QString getFTBAPath() { + return FS::PathCombine(QDir::homePath(), ".ftba"); } #endif +QString getFTBASettingsPath() { + return FS::PathCombine(getFTBAPath(), "bin/settings.json"); +} + +QString getFTBAVersionPath(const QString& id) { + return FS::PathCombine(getFTBAPath(), QString("bin/versions/%1/%1.json").arg(id)); +} + QString getFTBAInstances() { QByteArray data; auto settingsPath = getFTBASettingsPath(); @@ -155,6 +164,90 @@ Reference from an FTB App file, as of 28.05.2022 } */ +void resolveModloader(QString mcVersion, ModLoader &loader) { + if(loader.id.isEmpty()) { + loader.type = ModLoaderType::None; + return; + } + auto path = getFTBAVersionPath(loader.id); + QByteArray data; + + try + { + data = FS::read(path); + } + catch (const Exception &e) + { + qWarning() << "Could not resolve modloader ID: " << loader.id << "File cannot be loaded: " << path; + loader.type = ModLoaderType::Unresolved; + return; + } + try + { + QJsonDocument doc = Json::requireDocument(data); + QJsonObject root = Json::requireObject(doc, "version.json"); + for (auto library: Json::ensureArray(root, "libraries", {})) + { + if (!library.isObject()) + { + continue; + } + + auto libraryObject = Json::ensureValueObject(library, {}, ""); + GradleSpecifier name = Json::requireString(libraryObject, "name"); + auto artifactPrefix = name.artifactPrefix(); + + if(artifactPrefix == "net.minecraftforge:forge") { + QString libraryVersion = name.version(); + loader.type = ModLoaderType::Forge; + // remove any garbage 'minecraft version' prefix / suffix + libraryVersion.remove(QString("%1-").arg(mcVersion)); + libraryVersion.remove(QString("-%1").arg(mcVersion)); + loader.version = libraryVersion; + return; + } + else if(artifactPrefix == "net.minecraftforge:minecraftforge") { + loader.type = ModLoaderType::Forge; + loader.version = name.version(); + return; + } + else if (artifactPrefix == "net.fabricmc:fabric-loader") + { + loader.type = ModLoaderType::Fabric; + loader.version = name.version(); + return; + } + else if (artifactPrefix == "org.quiltmc:quilt-loader") + { + loader.type = ModLoaderType::Quilt; + loader.version = name.version(); + return; + } + } + // Weird detection for 'modern' forge + QJsonObject arguments = Json::ensureObject(root, "arguments"); + auto gameArgs = Json::ensureArray(arguments, "game"); + bool versionIsNext = false; + for (auto arg: gameArgs) { + QString value = Json::ensureValueString(arg, QString()); + if(versionIsNext) { + loader.type = ModLoaderType::Forge; + loader.version = value; + break; + } + if(value == "--fml.forgeVersion") { + versionIsNext = true; + } + } + return; + } + catch (const JSONValidationError &e) + { + qWarning() << "Could not resolve modloader ID: " << loader.id << "File cannot be understood: " << path << "Error: " << e.cause(); + loader.type = ModLoaderType::Unresolved; + } +} + bool parseModpackJson(const QByteArray& data, Modpack & out) { try { @@ -173,9 +266,9 @@ bool parseModpackJson(const QByteArray& data, Modpack & out) { out.authors.append(Json::requireValueString(author)); } - out.mcVersion = Json::requireString(object, "mcVersion"); - out.modLoader = Json::ensureString(object, "modLoader", QString()); + out.modLoader.id = Json::ensureString(object, "modLoader", QString()); + resolveModloader(out.mcVersion, out.modLoader); out.hasInstMods = Json::ensureBoolean(object, "hasInstMods", false); out.minMemory = Json::ensureInteger(object, "minMemory", 1024); diff --git a/launcher/ui/pages/modplatform/import_ftb/Model.h b/launcher/ui/pages/modplatform/import_ftb/Model.h index dad2d38b..765ba22e 100644 --- a/launcher/ui/pages/modplatform/import_ftb/Model.h +++ b/launcher/ui/pages/modplatform/import_ftb/Model.h @@ -21,8 +21,21 @@ namespace ImportFTB { -struct Modpack -{ +enum class ModLoaderType { + Unresolved, + None, + Forge, + Fabric, + Quilt +}; + +struct ModLoader { + QString id; + ModLoaderType type = ModLoaderType::Unresolved; + QString version; +}; + +struct Modpack { int id = 0; int versionId = 0; @@ -32,7 +45,7 @@ struct Modpack QStringList authors; QString mcVersion; - QString modLoader; + ModLoader modLoader; bool hasInstMods = false; int minMemory = 1024; diff --git a/launcher/ui/pages/modplatform/import_ftb/PackInstallTask.cpp b/launcher/ui/pages/modplatform/import_ftb/PackInstallTask.cpp index 72c47831..0e1a7333 100644 --- a/launcher/ui/pages/modplatform/import_ftb/PackInstallTask.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/PackInstallTask.cpp @@ -53,16 +53,27 @@ void PackInstallTask::copyFinished() { components->setComponentVersion("net.minecraft", m_pack.mcVersion, true); auto modloader = m_pack.modLoader; - if(!modloader.isEmpty()) { - if(modloader.contains("-forge-")) { - auto forgeVersion = modloader.replace(m_pack.mcVersion, "").replace("-forge-", ""); - components->setComponentVersion("net.minecraftforge", forgeVersion, true); + switch(modloader.type) { + case ModLoaderType::None: { + // NOOP + break; } - else { - qWarning() << "Unknown modloader version: " << modloader; + case ModLoaderType::Forge: { + components->setComponentVersion("net.minecraftforge", modloader.version, true); + break; + } + case ModLoaderType::Fabric: { + components->setComponentVersion("net.fabricmc.fabric-loader", modloader.version, true); + break; + } + case ModLoaderType::Quilt: { + components->setComponentVersion("org.quiltmc.quilt-loader", modloader.version, true); + break; + } + case ModLoaderType::Unresolved: { + qWarning() << "Unknown modloader version: " << modloader.id; } } - components->saveNow(); instance.setName(m_instName);