From 0a827ba70e6ef20187f8507a536d54a8441020dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Thu, 19 May 2022 20:42:03 +0200 Subject: [PATCH] NOISSUE Remove FTB and Curse integration This has been requested by Slowpoke, on behalf of both FTB and OverWolf. Import from locally installed packs from the official clients will be the replacement, but for now, you will have to do that manually. It was nice while it lasted. --- buildconfig/BuildConfig.h | 2 - launcher/Application.cpp | 2 - launcher/CMakeLists.txt | 36 -- launcher/InstanceImportTask.cpp | 222 ----------- launcher/InstanceImportTask.h | 1 - .../modplatform/flame/FileResolvingTask.cpp | 63 ---- .../modplatform/flame/FileResolvingTask.h | 33 -- launcher/modplatform/flame/FlamePackIndex.cpp | 92 ----- launcher/modplatform/flame/FlamePackIndex.h | 41 -- launcher/modplatform/flame/PackManifest.cpp | 126 ------- launcher/modplatform/flame/PackManifest.h | 62 ---- .../modpacksch/FTBPackInstallTask.cpp | 259 ------------- .../modpacksch/FTBPackInstallTask.h | 67 ---- .../modpacksch/FTBPackManifest.cpp | 194 ---------- .../modplatform/modpacksch/FTBPackManifest.h | 144 -------- .../modplatform/modpacksch/MCHPackType.cpp | 34 -- launcher/modplatform/modpacksch/MCHPackType.h | 30 -- launcher/ui/dialogs/NewInstanceDialog.cpp | 5 - .../ui/pages/modplatform/flame/FlameModel.cpp | 258 ------------- .../ui/pages/modplatform/flame/FlameModel.h | 76 ---- .../ui/pages/modplatform/flame/FlamePage.cpp | 186 ---------- .../ui/pages/modplatform/flame/FlamePage.h | 80 ---- .../ui/pages/modplatform/flame/FlamePage.ui | 90 ----- .../modplatform/modpacksch/CursePage.cpp | 168 --------- .../pages/modplatform/modpacksch/CursePage.h | 83 ----- .../pages/modplatform/modpacksch/CursePage.ui | 86 ----- .../pages/modplatform/modpacksch/FtbPage.cpp | 169 --------- .../ui/pages/modplatform/modpacksch/FtbPage.h | 83 ----- .../pages/modplatform/modpacksch/FtbPage.ui | 79 ---- .../modplatform/modpacksch/MCHFilterModel.cpp | 92 ----- .../modplatform/modpacksch/MCHFilterModel.h | 51 --- .../modplatform/modpacksch/MCHListModel.cpp | 349 ------------------ .../modplatform/modpacksch/MCHListModel.h | 88 ----- 33 files changed, 3351 deletions(-) delete mode 100644 launcher/modplatform/flame/FileResolvingTask.cpp delete mode 100644 launcher/modplatform/flame/FileResolvingTask.h delete mode 100644 launcher/modplatform/flame/FlamePackIndex.cpp delete mode 100644 launcher/modplatform/flame/FlamePackIndex.h delete mode 100644 launcher/modplatform/flame/PackManifest.cpp delete mode 100644 launcher/modplatform/flame/PackManifest.h delete mode 100644 launcher/modplatform/modpacksch/FTBPackInstallTask.cpp delete mode 100644 launcher/modplatform/modpacksch/FTBPackInstallTask.h delete mode 100644 launcher/modplatform/modpacksch/FTBPackManifest.cpp delete mode 100644 launcher/modplatform/modpacksch/FTBPackManifest.h delete mode 100644 launcher/modplatform/modpacksch/MCHPackType.cpp delete mode 100644 launcher/modplatform/modpacksch/MCHPackType.h delete mode 100644 launcher/ui/pages/modplatform/flame/FlameModel.cpp delete mode 100644 launcher/ui/pages/modplatform/flame/FlameModel.h delete mode 100644 launcher/ui/pages/modplatform/flame/FlamePage.cpp delete mode 100644 launcher/ui/pages/modplatform/flame/FlamePage.h delete mode 100644 launcher/ui/pages/modplatform/flame/FlamePage.ui delete mode 100644 launcher/ui/pages/modplatform/modpacksch/CursePage.cpp delete mode 100644 launcher/ui/pages/modplatform/modpacksch/CursePage.h delete mode 100644 launcher/ui/pages/modplatform/modpacksch/CursePage.ui delete mode 100644 launcher/ui/pages/modplatform/modpacksch/FtbPage.cpp delete mode 100644 launcher/ui/pages/modplatform/modpacksch/FtbPage.h delete mode 100644 launcher/ui/pages/modplatform/modpacksch/FtbPage.ui delete mode 100644 launcher/ui/pages/modplatform/modpacksch/MCHFilterModel.cpp delete mode 100644 launcher/ui/pages/modplatform/modpacksch/MCHFilterModel.h delete mode 100644 launcher/ui/pages/modplatform/modpacksch/MCHListModel.cpp delete mode 100644 launcher/ui/pages/modplatform/modpacksch/MCHListModel.h diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index ac05f288..903827ea 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -96,8 +96,6 @@ public: QString FMLLIBS_BASE_URL = "https://files.multimc.org/fmllibs/"; QString TRANSLATIONS_BASE_URL = "https://files.multimc.org/translations/"; - QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/"; - QString LEGACY_FTB_CDN_BASE_URL = "https://dist.creeper.host/FTB2/"; QString ATL_DOWNLOAD_SERVER_URL = "https://download.nodecdn.net/containers/atl/"; diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 97e9d225..b0e029ad 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -856,9 +856,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_metacache->addBase("general", QDir("cache").absolutePath()); m_metacache->addBase("ATLauncherPacks", QDir("cache/ATLauncherPacks").absolutePath()); m_metacache->addBase("FTBPacks", QDir("cache/FTBPacks").absolutePath()); - m_metacache->addBase("ModpacksCHPacks", QDir("cache/ModpacksCHPacks").absolutePath()); m_metacache->addBase("TechnicPacks", QDir("cache/TechnicPacks").absolutePath()); - m_metacache->addBase("FlamePacks", QDir("cache/FlamePacks").absolutePath()); m_metacache->addBase("ModrinthPacks", QDir("cache/ModrinthPacks").absolutePath()); m_metacache->addBase("root", QDir::currentPath()); m_metacache->addBase("translations", QDir("translations").absolutePath()); diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index a87e2a7c..888e09e1 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -504,25 +504,6 @@ set(FTB_SOURCES modplatform/legacy_ftb/PackHelpers.h ) -set(FLAME_SOURCES - # Flame - modplatform/flame/FlamePackIndex.cpp - modplatform/flame/FlamePackIndex.h - modplatform/flame/PackManifest.h - modplatform/flame/PackManifest.cpp - modplatform/flame/FileResolvingTask.h - modplatform/flame/FileResolvingTask.cpp -) - -set(MODPACKSCH_SOURCES - modplatform/modpacksch/FTBPackInstallTask.h - modplatform/modpacksch/FTBPackInstallTask.cpp - modplatform/modpacksch/FTBPackManifest.h - modplatform/modpacksch/FTBPackManifest.cpp - modplatform/modpacksch/MCHPackType.h - modplatform/modpacksch/MCHPackType.cpp -) - set(TECHNIC_SOURCES modplatform/technic/SingleZipPackInstallTask.h modplatform/technic/SingleZipPackInstallTask.cpp @@ -735,25 +716,11 @@ SET(LAUNCHER_SOURCES ui/pages/modplatform/atlauncher/AtlPage.cpp ui/pages/modplatform/atlauncher/AtlPage.h - ui/pages/modplatform/modpacksch/MCHFilterModel.cpp - ui/pages/modplatform/modpacksch/MCHFilterModel.h - ui/pages/modplatform/modpacksch/MCHListModel.cpp - ui/pages/modplatform/modpacksch/MCHListModel.h - ui/pages/modplatform/modpacksch/FtbPage.cpp - ui/pages/modplatform/modpacksch/FtbPage.h - ui/pages/modplatform/modpacksch/CursePage.cpp - ui/pages/modplatform/modpacksch/CursePage.h - ui/pages/modplatform/legacy_ftb/Page.cpp ui/pages/modplatform/legacy_ftb/Page.h ui/pages/modplatform/legacy_ftb/ListModel.h ui/pages/modplatform/legacy_ftb/ListModel.cpp - ui/pages/modplatform/flame/FlameModel.cpp - ui/pages/modplatform/flame/FlameModel.h - ui/pages/modplatform/flame/FlamePage.cpp - ui/pages/modplatform/flame/FlamePage.h - ui/pages/modplatform/modrinth/ModrinthData.h ui/pages/modplatform/modrinth/ModrinthModel.cpp ui/pages/modplatform/modrinth/ModrinthModel.h @@ -880,11 +847,8 @@ qt5_wrap_ui(LAUNCHER_UI ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui ui/pages/modplatform/atlauncher/AtlPage.ui ui/pages/modplatform/VanillaPage.ui - ui/pages/modplatform/flame/FlamePage.ui ui/pages/modplatform/legacy_ftb/Page.ui ui/pages/modplatform/ImportPage.ui - ui/pages/modplatform/modpacksch/FtbPage.ui - ui/pages/modplatform/modpacksch/CursePage.ui ui/pages/modplatform/modrinth/ModrinthPage.ui ui/pages/modplatform/technic/TechnicPage.ui ui/widgets/InstanceCardWidget.ui diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 6fa8b2b6..89d4053e 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -26,8 +26,6 @@ // FIXME: this does not belong here, it's Minecraft/Flame specific #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" -#include "modplatform/flame/FileResolvingTask.h" -#include "modplatform/flame/PackManifest.h" #include "Json.h" #include #include "modplatform/modrinth/ModrinthPackManifest.h" @@ -105,7 +103,6 @@ void InstanceImportTask::processZipPack() QStringList blacklist = {"instance.cfg", "manifest.json"}; QString mmcFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg"); bool technicFound = QuaZipDir(m_packZip.get()).exists("/bin/modpack.jar") || QuaZipDir(m_packZip.get()).exists("/bin/version.json"); - QString flameFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json"); QString modrinthFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "modrinth.index.json"); QString root; if(!mmcFound.isNull()) @@ -123,13 +120,6 @@ void InstanceImportTask::processZipPack() extractDir.cd(".minecraft"); m_modpackType = ModpackType::Technic; } - else if(!flameFound.isNull()) - { - // process as Flame pack - qDebug() << "Flame:" << flameFound; - root = flameFound; - m_modpackType = ModpackType::Flame; - } else if(!modrinthFound.isNull()) { // process as Modrinth pack @@ -199,9 +189,6 @@ void InstanceImportTask::extractFinished() case ModpackType::Technic: processTechnic(); return; - case ModpackType::Flame: - processFlame(); - return; case ModpackType::Modrinth: processModrinth(); return; @@ -217,215 +204,6 @@ void InstanceImportTask::extractAborted() return; } -void InstanceImportTask::processFlame() -{ - const static QMap forgemap = { - {"1.2.5", "3.4.9.171"}, - {"1.4.2", "6.0.1.355"}, - {"1.4.7", "6.6.2.534"}, - {"1.5.2", "7.8.1.737"} - }; - Flame::Manifest pack; - try - { - QString configPath = FS::PathCombine(m_stagingPath, "manifest.json"); - Flame::loadManifest(pack, configPath); - QFile::remove(configPath); - } - catch (const JSONValidationError &e) - { - emitFailed(tr("Could not understand pack manifest:\n") + e.cause()); - return; - } - if(!pack.overrides.isEmpty()) - { - QString overridePath = FS::PathCombine(m_stagingPath, pack.overrides); - if (QFile::exists(overridePath)) - { - QString mcPath = FS::PathCombine(m_stagingPath, "minecraft"); - if (!QFile::rename(overridePath, mcPath)) - { - emitFailed(tr("Could not rename the overrides folder:\n") + pack.overrides); - return; - } - } - else - { - logWarning(tr("The specified overrides folder (%1) is missing. Maybe the modpack was already used before?").arg(pack.overrides)); - } - } - - QString forgeVersion; - QString fabricVersion; - for(auto &loader: pack.minecraft.modLoaders) - { - auto id = loader.id; - if(id.startsWith("forge-")) - { - id.remove("forge-"); - forgeVersion = id; - continue; - } - if(id.startsWith("fabric-")) - { - id.remove("fabric-"); - fabricVersion = id; - continue; - } - logWarning(tr("Unknown mod loader in manifest: %1").arg(id)); - } - - QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg"); - auto instanceSettings = std::make_shared(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'... - if(mcVersion.endsWith('.')) - { - mcVersion.remove(QRegExp("[.]+$")); - logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack.")); - } - auto components = instance.getPackProfile(); - components->buildingFromScratch(); - components->setComponentVersion("net.minecraft", mcVersion, true); - if(!forgeVersion.isEmpty()) - { - // FIXME: dirty, nasty, hack. Proper solution requires dependency resolution and knowledge of the metadata. - if(forgeVersion == "recommended") - { - if(forgemap.contains(mcVersion)) - { - forgeVersion = forgemap[mcVersion]; - } - else - { - logWarning(tr("Could not map recommended forge version for Minecraft %1").arg(mcVersion)); - } - } - components->setComponentVersion("net.minecraftforge", forgeVersion); - } - if(!fabricVersion.isEmpty()) - { - components->setComponentVersion("net.fabricmc.fabric-loader", fabricVersion); - } - if (m_instIcon != "default") - { - instance.setIconKey(m_instIcon); - } - else - { - if(pack.name.contains("Direwolf20")) - { - instance.setIconKey("steve"); - } - else if(pack.name.contains("FTB") || pack.name.contains("Feed The Beast")) - { - instance.setIconKey("ftb_logo"); - } - else - { - // default to something other than the MultiMC default to distinguish these - instance.setIconKey("flame"); - } - } - QString jarmodsPath = FS::PathCombine(m_stagingPath, "minecraft", "jarmods"); - QFileInfo jarmodsInfo(jarmodsPath); - if(jarmodsInfo.isDir()) - { - // install all the jar mods - qDebug() << "Found jarmods:"; - QDir jarmodsDir(jarmodsPath); - QStringList jarMods; - for (auto info: jarmodsDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files)) - { - qDebug() << info.fileName(); - jarMods.push_back(info.absoluteFilePath()); - } - auto profile = instance.getPackProfile(); - profile->installJarMods(jarMods); - // nuke the original files - FS::deletePath(jarmodsPath); - } - instance.setName(m_instName); - m_modIdResolver = new Flame::FileResolvingTask(APPLICATION->network(), pack); - connect(m_modIdResolver.get(), &Flame::FileResolvingTask::succeeded, [&]() - { - auto results = m_modIdResolver->getResults(); - m_filesNetJob = new NetJob(tr("Mod download"), APPLICATION->network()); - for(auto result: results.files) - { - QString filename = result.fileName; - if(!result.required) - { - filename += ".disabled"; - } - - auto relpath = FS::PathCombine("minecraft", result.targetFolder, filename); - auto path = FS::PathCombine(m_stagingPath , relpath); - - switch(result.type) - { - case Flame::File::Type::Folder: - { - logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath)); - // fall-through intentional, we treat these as plain old mods and dump them wherever. - } - case Flame::File::Type::SingleFile: - case Flame::File::Type::Mod: - { - qDebug() << "Will download" << result.url << "to" << path; - auto dl = Net::Download::makeFile(result.url, path); - m_filesNetJob->addNetAction(dl); - break; - } - case Flame::File::Type::Modpack: - logWarning(tr("Nesting modpacks in modpacks is not implemented, nothing was downloaded: %1").arg(relpath)); - break; - case Flame::File::Type::Cmod2: - case Flame::File::Type::Ctoc: - case Flame::File::Type::Unknown: - logWarning(tr("Unrecognized/unhandled PackageType for: %1").arg(relpath)); - break; - } - } - m_modIdResolver.reset(); - connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]() - { - m_filesNetJob.reset(); - emitSucceeded(); - } - ); - connect(m_filesNetJob.get(), &NetJob::failed, [&](QString reason) - { - m_filesNetJob.reset(); - emitFailed(reason); - }); - connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total) - { - setProgress(current, total); - }); - setStatus(tr("Downloading mods...")); - m_filesNetJob->start(); - } - ); - connect(m_modIdResolver.get(), &Flame::FileResolvingTask::failed, [&](QString reason) - { - m_modIdResolver.reset(); - emitFailed(tr("Unable to resolve mod IDs:\n") + reason); - }); - connect(m_modIdResolver.get(), &Flame::FileResolvingTask::progress, [&](qint64 current, qint64 total) - { - setProgress(current, total); - }); - connect(m_modIdResolver.get(), &Flame::FileResolvingTask::status, [&](QString status) - { - setStatus(status); - }); - m_modIdResolver->start(); -} - void InstanceImportTask::processTechnic() { shared_qobject_ptr packProcessor = new Technic::TechnicPackProcessor(); diff --git a/launcher/InstanceImportTask.h b/launcher/InstanceImportTask.h index 0a60b1e5..c161f10b 100644 --- a/launcher/InstanceImportTask.h +++ b/launcher/InstanceImportTask.h @@ -68,7 +68,6 @@ private: /* data */ Unknown, MultiMC, Technic, - Flame, Modrinth, } m_modpackType = ModpackType::Unknown; }; diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp deleted file mode 100644 index 3889a935..00000000 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "FileResolvingTask.h" -#include "Json.h" - -namespace { - const char * metabase = "https://cursemeta.dries007.net"; -} - -Flame::FileResolvingTask::FileResolvingTask(shared_qobject_ptr network, Flame::Manifest& toProcess) - : m_network(network), m_toProcess(toProcess) -{ -} - -void Flame::FileResolvingTask::executeTask() -{ - setStatus(tr("Resolving mod IDs...")); - setProgress(0, m_toProcess.files.size()); - m_dljob = new NetJob("Mod id resolver", m_network); - results.resize(m_toProcess.files.size()); - int index = 0; - for(auto & file: m_toProcess.files) - { - auto projectIdStr = QString::number(file.projectId); - auto fileIdStr = QString::number(file.fileId); - QString metaurl = QString("%1/%2/%3.json").arg(metabase, projectIdStr, fileIdStr); - auto dl = Net::Download::makeByteArray(QUrl(metaurl), &results[index]); - m_dljob->addNetAction(dl); - index ++; - } - connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished); - m_dljob->start(); -} - -void Flame::FileResolvingTask::netJobFinished() -{ - bool failed = false; - int index = 0; - for(auto & bytes: results) - { - auto & out = m_toProcess.files[index]; - try - { - failed &= (!out.parseFromBytes(bytes)); - } - catch (const JSONValidationError &e) - { - - qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of a parsing error:"; - qCritical() << e.cause(); - qCritical() << "JSON:"; - qCritical() << bytes; - failed = true; - } - index++; - } - if(!failed) - { - emitSucceeded(); - } - else - { - emitFailed(tr("Some mod ID resolving tasks failed.")); - } -} diff --git a/launcher/modplatform/flame/FileResolvingTask.h b/launcher/modplatform/flame/FileResolvingTask.h deleted file mode 100644 index 5e5adcd7..00000000 --- a/launcher/modplatform/flame/FileResolvingTask.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "tasks/Task.h" -#include "net/NetJob.h" -#include "PackManifest.h" - -namespace Flame -{ -class FileResolvingTask : public Task -{ - Q_OBJECT -public: - explicit FileResolvingTask(shared_qobject_ptr network, Flame::Manifest &toProcess); - virtual ~FileResolvingTask() {}; - - const Flame::Manifest &getResults() const - { - return m_toProcess; - } - -protected: - virtual void executeTask() override; - -protected slots: - void netJobFinished(); - -private: /* data */ - shared_qobject_ptr m_network; - Flame::Manifest m_toProcess; - QVector results; - NetJob::Ptr m_dljob; -}; -} diff --git a/launcher/modplatform/flame/FlamePackIndex.cpp b/launcher/modplatform/flame/FlamePackIndex.cpp deleted file mode 100644 index 3d8ea22a..00000000 --- a/launcher/modplatform/flame/FlamePackIndex.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "FlamePackIndex.h" - -#include "Json.h" - -void Flame::loadIndexedPack(Flame::IndexedPack & pack, QJsonObject & obj) -{ - pack.addonId = Json::requireInteger(obj, "id"); - pack.name = Json::requireString(obj, "name"); - pack.websiteUrl = Json::ensureString(obj, "websiteUrl", ""); - pack.description = Json::ensureString(obj, "summary", ""); - - bool thumbnailFound = false; - auto attachments = Json::requireArray(obj, "attachments"); - for(auto attachmentRaw: attachments) { - auto attachmentObj = Json::requireObject(attachmentRaw); - bool isDefault = attachmentObj.value("isDefault").toBool(false); - if(isDefault) { - thumbnailFound = true; - pack.logoName = Json::requireString(attachmentObj, "title"); - pack.logoUrl = Json::requireString(attachmentObj, "thumbnailUrl"); - break; - } - } - - if(!thumbnailFound) { - throw JSONValidationError(QString("Pack without an icon, skipping: %1").arg(pack.name)); - } - - auto authors = Json::requireArray(obj, "authors"); - for(auto authorIter: authors) { - auto author = Json::requireObject(authorIter); - Flame::ModpackAuthor packAuthor; - packAuthor.name = Json::requireString(author, "name"); - packAuthor.url = Json::requireString(author, "url"); - pack.authors.append(packAuthor); - } - int defaultFileId = Json::requireInteger(obj, "defaultFileId"); - - bool found = false; - // check if there are some files before adding the pack - auto files = Json::requireArray(obj, "latestFiles"); - for(auto fileIter: files) { - auto file = Json::requireObject(fileIter); - int id = Json::requireInteger(file, "id"); - - // NOTE: for now, ignore everything that's not the default... - if(id != defaultFileId) { - continue; - } - - auto versionArray = Json::requireArray(file, "gameVersion"); - if(versionArray.size() < 1) { - continue; - } - - found = true; - break; - } - if(!found) { - throw JSONValidationError(QString("Pack with no good file, skipping: %1").arg(pack.name)); - } -} - -void Flame::loadIndexedPackVersions(Flame::IndexedPack & pack, QJsonArray & arr) -{ - QVector unsortedVersions; - for(auto versionIter: arr) { - auto version = Json::requireObject(versionIter); - Flame::IndexedVersion file; - - file.addonId = pack.addonId; - file.fileId = Json::requireInteger(version, "id"); - auto versionArray = Json::requireArray(version, "gameVersion"); - if(versionArray.size() < 1) { - continue; - } - - // pick the latest version supported - file.mcVersion = versionArray[0].toString(); - file.version = Json::requireString(version, "displayName"); - file.downloadUrl = Json::requireString(version, "downloadUrl"); - unsortedVersions.append(file); - } - - auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool - { - return a.fileId > b.fileId; - }; - std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); - pack.versions = unsortedVersions; - pack.versionsLoaded = true; -} diff --git a/launcher/modplatform/flame/FlamePackIndex.h b/launcher/modplatform/flame/FlamePackIndex.h deleted file mode 100644 index 7ffa29c3..00000000 --- a/launcher/modplatform/flame/FlamePackIndex.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace Flame { - -struct ModpackAuthor { - QString name; - QString url; -}; - -struct IndexedVersion { - int addonId; - int fileId; - QString version; - QString mcVersion; - QString downloadUrl; -}; - -struct IndexedPack -{ - int addonId; - QString name; - QString description; - QList authors; - QString logoName; - QString logoUrl; - QString websiteUrl; - - bool versionsLoaded = false; - QVector versions; -}; - -void loadIndexedPack(IndexedPack & m, QJsonObject & obj); -void loadIndexedPackVersions(IndexedPack & m, QJsonArray & arr); -} - -Q_DECLARE_METATYPE(Flame::IndexedPack) diff --git a/launcher/modplatform/flame/PackManifest.cpp b/launcher/modplatform/flame/PackManifest.cpp deleted file mode 100644 index b928fd16..00000000 --- a/launcher/modplatform/flame/PackManifest.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "PackManifest.h" -#include "Json.h" - -static void loadFileV1(Flame::File & f, QJsonObject & file) -{ - f.projectId = Json::requireInteger(file, "projectID"); - f.fileId = Json::requireInteger(file, "fileID"); - f.required = Json::ensureBoolean(file, QString("required"), true); -} - -static void loadModloaderV1(Flame::Modloader & m, QJsonObject & modLoader) -{ - m.id = Json::requireString(modLoader, "id"); - m.primary = Json::ensureBoolean(modLoader, QString("primary"), false); -} - -static void loadMinecraftV1(Flame::Minecraft & m, QJsonObject & minecraft) -{ - m.version = Json::requireString(minecraft, "version"); - // extra libraries... apparently only used for a custom Minecraft launcher in the 1.2.5 FTB retro pack - // intended use is likely hardcoded in the 'Flame' client, the manifest says nothing - m.libraries = Json::ensureString(minecraft, QString("libraries"), QString()); - auto arr = Json::ensureArray(minecraft, "modLoaders", QJsonArray()); - for (QJsonValueRef item : arr) - { - auto obj = Json::requireObject(item); - Flame::Modloader loader; - loadModloaderV1(loader, obj); - m.modLoaders.append(loader); - } -} - -static void loadManifestV1(Flame::Manifest & m, QJsonObject & manifest) -{ - auto mc = Json::requireObject(manifest, "minecraft"); - loadMinecraftV1(m.minecraft, mc); - m.name = Json::ensureString(manifest, QString("name"), "Unnamed"); - m.version = Json::ensureString(manifest, QString("version"), QString()); - m.author = Json::ensureString(manifest, QString("author"), "Anonymous Coward"); - auto arr = Json::ensureArray(manifest, "files", QJsonArray()); - for (QJsonValueRef item : arr) - { - auto obj = Json::requireObject(item); - Flame::File file; - loadFileV1(file, obj); - m.files.append(file); - } - m.overrides = Json::ensureString(manifest, "overrides", "overrides"); -} - -void Flame::loadManifest(Flame::Manifest & m, const QString &filepath) -{ - auto doc = Json::requireDocument(filepath); - auto obj = Json::requireObject(doc); - m.manifestType = Json::requireString(obj, "manifestType"); - if(m.manifestType != "minecraftModpack") - { - throw JSONValidationError("Not a modpack manifest!"); - } - m.manifestVersion = Json::requireInteger(obj, "manifestVersion"); - if(m.manifestVersion != 1) - { - throw JSONValidationError(QString("Unknown manifest version (%1)").arg(m.manifestVersion)); - } - loadManifestV1(m, obj); -} - -bool Flame::File::parseFromBytes(const QByteArray& bytes) -{ - auto doc = Json::requireDocument(bytes); - auto obj = Json::requireObject(doc); - // result code signifies true failure. - if(obj.contains("code")) - { - qCritical() << "Resolving of" << projectId << fileId << "failed because of a negative result:"; - qCritical() << bytes; - return false; - } - fileName = Json::requireString(obj, "FileNameOnDisk"); - QString rawUrl = Json::requireString(obj, "DownloadURL"); - url = QUrl(rawUrl, QUrl::TolerantMode); - if(!url.isValid()) - { - throw JSONValidationError(QString("Invalid URL: %1").arg(rawUrl)); - } - // This is a piece of a Flame project JSON pulled out into the file metadata (here) for convenience - // It is also optional - QJsonObject projObj = Json::ensureObject(obj, "_Project", {}); - if(!projObj.isEmpty()) - { - QString strType = Json::ensureString(projObj, "PackageType", "mod").toLower(); - if(strType == "singlefile") - { - type = File::Type::SingleFile; - } - else if(strType == "ctoc") - { - type = File::Type::Ctoc; - } - else if(strType == "cmod2") - { - type = File::Type::Cmod2; - } - else if(strType == "mod") - { - type = File::Type::Mod; - } - else if(strType == "folder") - { - type = File::Type::Folder; - } - else if(strType == "modpack") - { - type = File::Type::Modpack; - } - else - { - qCritical() << "Resolving of" << projectId << fileId << "failed because of unknown file type:" << strType; - type = File::Type::Unknown; - return false; - } - targetFolder = Json::ensureString(projObj, "Path", "mods"); - } - resolved = true; - return true; -} diff --git a/launcher/modplatform/flame/PackManifest.h b/launcher/modplatform/flame/PackManifest.h deleted file mode 100644 index 02f39f0e..00000000 --- a/launcher/modplatform/flame/PackManifest.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace Flame -{ -struct File -{ - // NOTE: throws JSONValidationError - bool parseFromBytes(const QByteArray &bytes); - - int projectId = 0; - int fileId = 0; - // NOTE: the opposite to 'optional'. This is at the time of writing unused. - bool required = true; - - // our - bool resolved = false; - QString fileName; - QUrl url; - QString targetFolder = QLatin1Literal("mods"); - enum class Type - { - Unknown, - Folder, - Ctoc, - SingleFile, - Cmod2, - Modpack, - Mod - } type = Type::Mod; -}; - -struct Modloader -{ - QString id; - bool primary = false; -}; - -struct Minecraft -{ - QString version; - QString libraries; - QVector modLoaders; -}; - -struct Manifest -{ - QString manifestType; - int manifestVersion = 0; - Flame::Minecraft minecraft; - QString name; - QString version; - QString author; - QVector files; - QString overrides; -}; - -void loadManifest(Flame::Manifest & m, const QString &filepath); -} diff --git a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp deleted file mode 100644 index 06934314..00000000 --- a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright 2020-2022 Jamie Mansfield - * Copyright 2020-2021 Petr Mrazek - * - * 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 "FTBPackInstallTask.h" - -#include "FileSystem.h" -#include "Json.h" -#include "MMCZip.h" -#include "minecraft/MinecraftInstance.h" -#include "minecraft/PackProfile.h" -#include "net/ChecksumValidator.h" -#include "settings/INISettingsObject.h" - -#include "BuildConfig.h" -#include "Application.h" - -namespace ModpacksCH { - -PackInstallTask::PackInstallTask(Modpack pack, QString version, PackType type) -{ - m_pack = pack; - m_version_name = version; - m_pack_type = type; -} - -bool PackInstallTask::abort() -{ - if(abortable) - { - return jobPtr->abort(); - } - return false; -} - -void PackInstallTask::executeTask() -{ - // Find pack version - bool found = false; - VersionInfo version; - - for(auto vInfo : m_pack.versions) { - if (vInfo.name == m_version_name) { - found = true; - version = vInfo; - break; - } - } - - if(!found) { - emitFailed(tr("Failed to find pack version %1").arg(m_version_name)); - return; - } - - auto *netJob = new NetJob("ModpacksCH::VersionFetch", APPLICATION->network()); - auto searchUrl = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/%1/%2/%3") - .arg(getRealmForPackType(m_pack_type)) - .arg(m_pack.id) - .arg(version.id); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); - jobPtr = netJob; - jobPtr->start(); - - QObject::connect(netJob, &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); - QObject::connect(netJob, &NetJob::failed, this, &PackInstallTask::onDownloadFailed); -} - -void PackInstallTask::onDownloadSucceeded() -{ - jobPtr.reset(); - - QJsonParseError parse_error {}; - QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); - if(parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from ModpacksCH at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << response; - return; - } - auto obj = doc.object(); - - ModpacksCH::Version version; - try - { - ModpacksCH::loadVersion(version, obj); - } - catch (const JSONValidationError &e) - { - emitFailed(tr("Could not understand pack manifest:\n") + e.cause()); - return; - } - m_version = version; - - downloadPack(); -} - -void PackInstallTask::onDownloadFailed(QString reason) -{ - jobPtr.reset(); - emitFailed(reason); -} - -void PackInstallTask::downloadPack() -{ - setStatus(tr("Downloading mods...")); - - jobPtr = new NetJob(tr("Mod download"), APPLICATION->network()); - for(auto file : m_version.files) { - if(file.serverOnly) continue; - - QFileInfo fileName(file.name); - auto cacheName = fileName.completeBaseName() + "-" + file.sha1 + "." + fileName.suffix(); - - auto entry = APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", cacheName); - entry->setStale(true); - - if (file.type == "cf-extract") { - filesToExtract[entry->getFullPath()] = file; - } - else { - auto relpath = FS::PathCombine("minecraft", file.path, file.name); - auto path = FS::PathCombine(m_stagingPath, relpath); - - if (filesToCopy.contains(path)) { - qWarning() << "Ignoring" << file.url << "as a file of that path is already downloading."; - continue; - } - qDebug() << "Will download" << file.url << "to" << path; - filesToCopy[path] = entry->getFullPath(); - } - - auto dl = Net::Download::makeCached(file.url, entry); - if (!file.sha1.isEmpty()) { - auto rawSha1 = QByteArray::fromHex(file.sha1.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); - } - jobPtr->addNetAction(dl); - } - - connect(jobPtr.get(), &NetJob::succeeded, this, [&]() - { - abortable = false; - jobPtr.reset(); - install(); - }); - connect(jobPtr.get(), &NetJob::failed, [&](QString reason) - { - abortable = false; - jobPtr.reset(); - emitFailed(reason); - }); - connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) - { - abortable = true; - setProgress(current, total); - }); - - jobPtr->start(); -} - -void PackInstallTask::install() -{ - if (!filesToCopy.isEmpty()) { - setStatus(tr("Copying modpack files")); - - for (auto iter = filesToCopy.begin(); iter != filesToCopy.end(); iter++) { - auto& to = iter.key(); - auto& from = iter.value(); - FS::copy fileCopyOperation(from, to); - if (!fileCopyOperation()) { - qWarning() << "Failed to copy" << from << "to" << to; - emitFailed(tr("Failed to copy files")); - return; - } - } - } - - if (!filesToExtract.isEmpty()) { - setStatus(tr("Extracting modpack files")); - - for (auto iter = filesToExtract.begin(); iter != filesToExtract.end(); iter++) { - auto& filePath = iter.key(); - auto& file = iter.value(); - - auto relpath = FS::PathCombine("minecraft", file.path); - auto path = FS::PathCombine(m_stagingPath, relpath); - - if (!MMCZip::extractDir(filePath, "overrides/", path)) { - qWarning() << "Failed to extract files from" << filePath << "to" << path; - emitFailed(tr("Failed to extract files")); - return; - } - } - } - - setStatus(tr("Installing modpack")); - - auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg"); - auto instanceSettings = std::make_shared(instanceConfigPath); - instanceSettings->suspendSave(); - instanceSettings->registerSetting("InstanceType", "Legacy"); - instanceSettings->set("InstanceType", "OneSix"); - - MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath); - auto components = instance.getPackProfile(); - components->buildingFromScratch(); - - for(auto target : m_version.targets) { - if(target.type == "game" && target.name == "minecraft") { - components->setComponentVersion("net.minecraft", target.version, true); - break; - } - } - - for(auto target : m_version.targets) { - if(target.type != "modloader") continue; - - if(target.name == "forge") { - components->setComponentVersion("net.minecraftforge", target.version, true); - } - else if(target.name == "fabric") { - components->setComponentVersion("net.fabricmc.fabric-loader", target.version, true); - } - } - - // install any jar mods - QDir jarModsDir(FS::PathCombine(m_stagingPath, "minecraft", "jarmods")); - if (jarModsDir.exists()) { - QStringList jarMods; - - for (const auto& info : jarModsDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files)) { - jarMods.push_back(info.absoluteFilePath()); - } - - components->installJarMods(jarMods); - } - - components->saveNow(); - - instance.setName(m_instName); - instance.setIconKey(m_instIcon); - instanceSettings->resumeSave(); - - emitSucceeded(); -} - -} diff --git a/launcher/modplatform/modpacksch/FTBPackInstallTask.h b/launcher/modplatform/modpacksch/FTBPackInstallTask.h deleted file mode 100644 index b82631f5..00000000 --- a/launcher/modplatform/modpacksch/FTBPackInstallTask.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2020-2022 Jamie Mansfield - * Copyright 2020-2021 Petr Mrazek - * - * 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 "FTBPackManifest.h" -#include "MCHPackType.h" - -#include "InstanceTask.h" -#include "net/NetJob.h" - -namespace ModpacksCH { - -class PackInstallTask : public InstanceTask -{ - Q_OBJECT - -public: - explicit PackInstallTask(Modpack pack, QString version, PackType type = PackType::FTB); - virtual ~PackInstallTask(){} - - bool canAbort() const override { return true; } - bool abort() override; - -protected: - virtual void executeTask() override; - -private slots: - void onDownloadSucceeded(); - void onDownloadFailed(QString reason); - -private: - void downloadPack(); - void install(); - -private: - bool abortable = false; - - NetJob::Ptr jobPtr; - QByteArray response; - - Modpack m_pack; - QString m_version_name; - Version m_version; - - PackType m_pack_type; - - QMap filesToExtract; - QMap filesToCopy; - -}; - -} diff --git a/launcher/modplatform/modpacksch/FTBPackManifest.cpp b/launcher/modplatform/modpacksch/FTBPackManifest.cpp deleted file mode 100644 index 68af788a..00000000 --- a/launcher/modplatform/modpacksch/FTBPackManifest.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2020-2022 Jamie Mansfield - * Copyright 2020-2021 Petr Mrazek - * - * 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 "FTBPackManifest.h" - -#include "Json.h" - -static void loadSpecs(ModpacksCH::Specs & s, QJsonObject & obj) -{ - s.id = Json::requireInteger(obj, "id"); - s.minimum = Json::requireInteger(obj, "minimum"); - s.recommended = Json::requireInteger(obj, "recommended"); -} - -static void loadTag(ModpacksCH::Tag & t, QJsonObject & obj) -{ - t.id = Json::requireInteger(obj, "id"); - t.name = Json::requireString(obj, "name"); -} - -static void loadArt(ModpacksCH::Art & a, QJsonObject & obj) -{ - a.id = Json::requireInteger(obj, "id"); - a.url = Json::requireString(obj, "url"); - a.type = Json::requireString(obj, "type"); - a.width = Json::requireInteger(obj, "width"); - a.height = Json::requireInteger(obj, "height"); - a.compressed = Json::requireBoolean(obj, "compressed"); - a.sha1 = Json::requireString(obj, "sha1"); - a.size = Json::requireInteger(obj, "size"); - a.updated = Json::requireInteger(obj, "updated"); -} - -static void loadAuthor(ModpacksCH::Author & a, QJsonObject & obj) -{ - a.id = Json::requireInteger(obj, "id"); - a.name = Json::requireString(obj, "name"); - a.type = Json::requireString(obj, "type"); - a.website = Json::requireString(obj, "website"); - a.updated = Json::requireInteger(obj, "updated"); -} - -static void loadVersionInfo(ModpacksCH::VersionInfo & v, QJsonObject & obj) -{ - v.id = Json::requireInteger(obj, "id"); - v.name = Json::requireString(obj, "name"); - v.type = Json::requireString(obj, "type"); - v.updated = Json::requireInteger(obj, "updated"); - - // CurseForge packs don't have specs. - if (obj.contains("specs")) { - auto specs = Json::requireObject(obj, "specs"); - loadSpecs(v.specs, specs); - } -} - -void ModpacksCH::loadModpack(ModpacksCH::Modpack & m, QJsonObject & obj) -{ - m.id = Json::requireInteger(obj, "id"); - m.name = Json::requireString(obj, "name"); - m.synopsis = Json::requireString(obj, "synopsis"); - m.description = Json::requireString(obj, "description"); - m.type = Json::requireString(obj, "type"); - m.featured = Json::requireBoolean(obj, "featured"); - m.installs = Json::requireInteger(obj, "installs"); - m.plays = Json::requireInteger(obj, "plays"); - m.updated = Json::requireInteger(obj, "updated"); - m.refreshed = Json::requireInteger(obj, "refreshed"); - auto artArr = Json::requireArray(obj, "art"); - for (QJsonValueRef artRaw : artArr) - { - auto artObj = Json::requireObject(artRaw); - ModpacksCH::Art art; - loadArt(art, artObj); - m.art.append(art); - } - auto authorArr = Json::requireArray(obj, "authors"); - for (QJsonValueRef authorRaw : authorArr) - { - auto authorObj = Json::requireObject(authorRaw); - ModpacksCH::Author author; - loadAuthor(author, authorObj); - m.authors.append(author); - } - auto versionArr = Json::requireArray(obj, "versions"); - for (QJsonValueRef versionRaw : versionArr) - { - auto versionObj = Json::requireObject(versionRaw); - ModpacksCH::VersionInfo version; - loadVersionInfo(version, versionObj); - m.versions.append(version); - } - auto tagArr = Json::requireArray(obj, "tags"); - for (QJsonValueRef tagRaw : tagArr) - { - auto tagObj = Json::requireObject(tagRaw); - ModpacksCH::Tag tag; - loadTag(tag, tagObj); - m.tags.append(tag); - } - m.updated = Json::requireInteger(obj, "updated"); -} - -static void loadVersionTarget(ModpacksCH::VersionTarget & a, QJsonObject & obj) -{ - a.id = Json::requireInteger(obj, "id"); - a.name = Json::requireString(obj, "name"); - a.type = Json::requireString(obj, "type"); - a.version = Json::requireString(obj, "version"); - a.updated = Json::requireInteger(obj, "updated"); -} - -static void loadVersionFile(ModpacksCH::VersionFile & a, QJsonObject & obj) -{ - a.id = Json::requireInteger(obj, "id"); - a.type = Json::requireString(obj, "type"); - a.path = Json::requireString(obj, "path"); - a.name = Json::requireString(obj, "name"); - - // This will be an integer with CurseForge packs. - auto versionVal = obj.value("version"); - if (versionVal.isString()) { - a.version = versionVal.toString(); - } - else if (versionVal.isDouble()) { - a.version = QString(versionVal.toInt()); - } - else { - throw Json::JsonException("'version' is not a string or integer"); - } - - a.url = Json::requireString(obj, "url"); - a.sha1 = Json::requireString(obj, "sha1"); - a.size = Json::requireInteger(obj, "size"); - a.clientOnly = Json::requireBoolean(obj, "clientonly"); - a.serverOnly = Json::requireBoolean(obj, "serveronly"); - a.optional = Json::requireBoolean(obj, "optional"); - a.updated = Json::requireInteger(obj, "updated"); -} - -void ModpacksCH::loadVersion(ModpacksCH::Version & m, QJsonObject & obj) -{ - m.id = Json::requireInteger(obj, "id"); - m.parent = Json::requireInteger(obj, "parent"); - m.name = Json::requireString(obj, "name"); - m.type = Json::requireString(obj, "type"); - m.installs = Json::requireInteger(obj, "installs"); - m.plays = Json::requireInteger(obj, "plays"); - m.updated = Json::requireInteger(obj, "updated"); - m.refreshed = Json::requireInteger(obj, "refreshed"); - - // CurseForge packs don't have specs. - if (obj.contains("specs")) { - auto specs = Json::requireObject(obj, "specs"); - loadSpecs(m.specs, specs); - } - - auto targetArr = Json::requireArray(obj, "targets"); - for (QJsonValueRef targetRaw : targetArr) - { - auto versionObj = Json::requireObject(targetRaw); - ModpacksCH::VersionTarget target; - loadVersionTarget(target, versionObj); - m.targets.append(target); - } - auto fileArr = Json::requireArray(obj, "files"); - for (QJsonValueRef fileRaw : fileArr) - { - auto fileObj = Json::requireObject(fileRaw); - ModpacksCH::VersionFile file; - loadVersionFile(file, fileObj); - m.files.append(file); - } -} - -//static void loadVersionChangelog(ModpacksCH::VersionChangelog & m, QJsonObject & obj) -//{ -// m.content = Json::requireString(obj, "content"); -// m.updated = Json::requireInteger(obj, "updated"); -//} diff --git a/launcher/modplatform/modpacksch/FTBPackManifest.h b/launcher/modplatform/modpacksch/FTBPackManifest.h deleted file mode 100644 index cf10a561..00000000 --- a/launcher/modplatform/modpacksch/FTBPackManifest.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2020-2021 Jamie Mansfield - * Copyright 2020 Petr Mrazek - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include "MCHPackType.h" - -namespace ModpacksCH -{ - -struct Specs -{ - int id; - int minimum; - int recommended; -}; - -struct Tag -{ - int id; - QString name; -}; - -struct Art -{ - int id; - QString url; - QString type; - int width; - int height; - bool compressed; - QString sha1; - int size; - int64_t updated; -}; - -struct Author -{ - int id; - QString name; - QString type; - QString website; - int64_t updated; -}; - -struct VersionInfo -{ - int id; - QString name; - QString type; - int64_t updated; - Specs specs; -}; - -struct Modpack -{ - PackType packType = PackType::FTB; - int id = 0; - QString name; - QString synopsis; - QString description; - QString type; - bool featured = false; - int installs = 0; - int plays = 0; - int64_t updated = 0; - int64_t refreshed = 0; - QVector art; - QVector authors; - QVector versions; - QVector tags; -}; - -struct VersionTarget -{ - int id; - QString type; - QString name; - QString version; - int64_t updated; -}; - -struct VersionFile -{ - int id; - QString type; - QString path; - QString name; - QString version; - QString url; - QString sha1; - int size; - bool clientOnly; - bool serverOnly; - bool optional; - int64_t updated; -}; - -struct Version -{ - int id; - int parent; - QString name; - QString type; - int installs; - int plays; - int64_t updated; - int64_t refreshed; - Specs specs; - QVector targets; - QVector files; -}; - -struct VersionChangelog -{ - QString content; - int64_t updated; -}; - -void loadModpack(Modpack & m, QJsonObject & obj); - -void loadVersion(Version & m, QJsonObject & obj); -} - -Q_DECLARE_METATYPE(ModpacksCH::Modpack) diff --git a/launcher/modplatform/modpacksch/MCHPackType.cpp b/launcher/modplatform/modpacksch/MCHPackType.cpp deleted file mode 100644 index 20fcfb84..00000000 --- a/launcher/modplatform/modpacksch/MCHPackType.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2022 Jamie Mansfield - * - * 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 "MCHPackType.h" - -#include - -namespace ModpacksCH { - -QString getRealmForPackType(PackType type) -{ - switch (type) { - case PackType::FTB: - return "modpack"; - case PackType::CurseForge: - return "curseforge"; - } - return "unknown"; -} - -} diff --git a/launcher/modplatform/modpacksch/MCHPackType.h b/launcher/modplatform/modpacksch/MCHPackType.h deleted file mode 100644 index 15742a0e..00000000 --- a/launcher/modplatform/modpacksch/MCHPackType.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2022 Jamie Mansfield - * - * 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 - -namespace ModpacksCH { - -enum class PackType { - FTB, - CurseForge, -}; - -QString getRealmForPackType(PackType type); - -} diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index e8966cd8..a9342f37 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -35,10 +35,7 @@ #include "ui/widgets/PageContainer.h" #include "ui/pages/modplatform/VanillaPage.h" #include "ui/pages/modplatform/atlauncher/AtlPage.h" -#include "ui/pages/modplatform/modpacksch/FtbPage.h" -#include "ui/pages/modplatform/modpacksch/CursePage.h" #include "ui/pages/modplatform/legacy_ftb/Page.h" -#include "ui/pages/modplatform/flame/FlamePage.h" #include "ui/pages/modplatform/ImportPage.h" #include "ui/pages/modplatform/modrinth/ModrinthPage.h" #include "ui/pages/modplatform/technic/TechnicPage.h" @@ -132,8 +129,6 @@ QList NewInstanceDialog::getPages() new VanillaPage(this), importPage, new AtlPage(this), - new CursePage(this), - new FtbPage(this), new LegacyFTB::Page(this), new ModrinthPage(this), technicPage diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp deleted file mode 100644 index 891676cf..00000000 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ /dev/null @@ -1,258 +0,0 @@ -#include "FlameModel.h" -#include "Application.h" -#include - -#include -#include - -#include -#include - -#include - -namespace Flame { - -ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) -{ -} - -ListModel::~ListModel() -{ -} - -int ListModel::rowCount(const QModelIndex &parent) const -{ - return modpacks.size(); -} - -int ListModel::columnCount(const QModelIndex &parent) const -{ - return 1; -} - -QVariant ListModel::data(const QModelIndex &index, int role) const -{ - int pos = index.row(); - if(pos >= modpacks.size() || pos < 0 || !index.isValid()) - { - return QString("INVALID INDEX %1").arg(pos); - } - - IndexedPack pack = modpacks.at(pos); - if(role == Qt::DisplayRole) - { - return pack.name; - } - else if (role == Qt::ToolTipRole) - { - if(pack.description.length() > 100) - { - //some magic to prevent to long tooltips and replace html linebreaks - QString edit = pack.description.left(97); - edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); - return edit; - - } - return pack.description; - } - else if(role == Qt::DecorationRole) - { - if(m_logoMap.contains(pack.logoName)) - { - return (m_logoMap.value(pack.logoName)); - } - QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); - ((ListModel *)this)->requestLogo(pack.logoName, pack.logoUrl); - return icon; - } - else if(role == Qt::UserRole) - { - QVariant v; - v.setValue(pack); - return v; - } - - return QVariant(); -} - -void ListModel::logoLoaded(QString logo, QIcon out) -{ - m_loadingLogos.removeAll(logo); - m_logoMap.insert(logo, out); - for(int i = 0; i < modpacks.size(); i++) { - if(modpacks[i].logoName == logo) { - emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole}); - } - } -} - -void ListModel::logoFailed(QString logo) -{ - m_failedLogos.append(logo); - m_loadingLogos.removeAll(logo); -} - -void ListModel::requestLogo(QString logo, QString url) -{ - if(m_loadingLogos.contains(logo) || m_failedLogos.contains(logo)) - { - return; - } - - MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo.section(".", 0, 0))); - NetJob *job = new NetJob(QString("Flame Icon Download %1").arg(logo), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); - - auto fullPath = entry->getFullPath(); - QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath] - { - emit logoLoaded(logo, QIcon(fullPath)); - if(waitingCallbacks.contains(logo)) - { - waitingCallbacks.value(logo)(fullPath); - } - }); - - QObject::connect(job, &NetJob::failed, this, [this, logo] - { - emit logoFailed(logo); - }); - - job->start(); - - m_loadingLogos.append(logo); -} - -void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback) -{ - if(m_logoMap.contains(logo)) - { - callback(APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); - } - else - { - requestLogo(logo, logoUrl); - } -} - -Qt::ItemFlags ListModel::flags(const QModelIndex &index) const -{ - return QAbstractListModel::flags(index); -} - -bool ListModel::canFetchMore(const QModelIndex& parent) const -{ - return searchState == CanPossiblyFetchMore; -} - -void ListModel::fetchMore(const QModelIndex& parent) -{ - if (parent.isValid()) - return; - if(nextSearchOffset == 0) { - qWarning() << "fetchMore with 0 offset is wrong..."; - return; - } - performPaginatedSearch(); -} - -void ListModel::performPaginatedSearch() -{ - NetJob *netJob = new NetJob("Flame::Search", APPLICATION->network()); - auto searchUrl = QString( - "https://addons-ecs.forgesvc.net/api/v2/addon/search?" - "categoryId=0&" - "gameId=432&" - "index=%1&" - "pageSize=25&" - "searchFilter=%2&" - "sectionId=4471&" - "sort=%3" - ).arg(nextSearchOffset).arg(currentSearchTerm).arg(currentSort); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); - jobPtr = netJob; - jobPtr->start(); - QObject::connect(netJob, &NetJob::succeeded, this, &ListModel::searchRequestFinished); - QObject::connect(netJob, &NetJob::failed, this, &ListModel::searchRequestFailed); -} - -void ListModel::searchWithTerm(const QString& term, int sort) -{ - if(currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort) { - return; - } - currentSearchTerm = term; - currentSort = sort; - if(jobPtr) { - jobPtr->abort(); - searchState = ResetRequested; - return; - } - else { - beginResetModel(); - modpacks.clear(); - endResetModel(); - searchState = None; - } - nextSearchOffset = 0; - performPaginatedSearch(); -} - -void Flame::ListModel::searchRequestFinished() -{ - jobPtr.reset(); - - QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); - if(parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from CurseForge at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << response; - return; - } - - QList newList; - auto packs = doc.array(); - for(auto packRaw : packs) { - auto packObj = packRaw.toObject(); - - Flame::IndexedPack pack; - try - { - Flame::loadIndexedPack(pack, packObj); - newList.append(pack); - } - catch(const JSONValidationError &e) - { - qWarning() << "Error while loading pack from CurseForge: " << e.cause(); - continue; - } - } - if(packs.size() < 25) { - searchState = Finished; - } else { - nextSearchOffset += 25; - searchState = CanPossiblyFetchMore; - } - beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + newList.size() - 1); - modpacks.append(newList); - endInsertRows(); -} - -void Flame::ListModel::searchRequestFailed(QString reason) -{ - jobPtr.reset(); - - if(searchState == ResetRequested) { - beginResetModel(); - modpacks.clear(); - endResetModel(); - - nextSearchOffset = 0; - performPaginatedSearch(); - } else { - searchState = Finished; - } -} - -} - diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.h b/launcher/ui/pages/modplatform/flame/FlameModel.h deleted file mode 100644 index 536f6add..00000000 --- a/launcher/ui/pages/modplatform/flame/FlameModel.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -namespace Flame { - - -typedef QMap LogoMap; -typedef std::function LogoCallback; - -class ListModel : public QAbstractListModel -{ - Q_OBJECT - -public: - ListModel(QObject *parent); - virtual ~ListModel(); - - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - bool canFetchMore(const QModelIndex & parent) const override; - void fetchMore(const QModelIndex & parent) override; - - void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback); - void searchWithTerm(const QString & term, const int sort); - -private slots: - void performPaginatedSearch(); - - void logoFailed(QString logo); - void logoLoaded(QString logo, QIcon out); - - void searchRequestFinished(); - void searchRequestFailed(QString reason); - -private: - void requestLogo(QString file, QString url); - -private: - QList modpacks; - QStringList m_failedLogos; - QStringList m_loadingLogos; - LogoMap m_logoMap; - QMap waitingCallbacks; - - QString currentSearchTerm; - int currentSort = 0; - int nextSearchOffset = 0; - enum SearchState { - None, - CanPossiblyFetchMore, - ResetRequested, - Finished - } searchState = None; - NetJob::Ptr jobPtr; - QByteArray response; -}; - -} diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp deleted file mode 100644 index 1138a298..00000000 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include "FlamePage.h" -#include "ui_FlamePage.h" - -#include - -#include "Application.h" -#include "Json.h" -#include "ui/dialogs/NewInstanceDialog.h" -#include "InstanceImportTask.h" -#include "FlameModel.h" - -FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget *parent) - : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog) -{ - ui->setupUi(this); - connect(ui->searchButton, &QPushButton::clicked, this, &FlamePage::triggerSearch); - ui->searchEdit->installEventFilter(this); - listModel = new Flame::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 curseforge 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 total downloads")); - - connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); - connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlamePage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlamePage::onVersionSelectionChanged); -} - -FlamePage::~FlamePage() -{ - delete ui; -} - -bool FlamePage::eventFilter(QObject* watched, QEvent* event) -{ - if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) { - QKeyEvent* keyEvent = static_cast(event); - if (keyEvent->key() == Qt::Key_Return) { - triggerSearch(); - keyEvent->accept(); - return true; - } - } - return QWidget::eventFilter(watched, event); -} - -bool FlamePage::shouldDisplay() const -{ - return true; -} - -void FlamePage::openedImpl() -{ - suggestCurrent(); - triggerSearch(); -} - -void FlamePage::triggerSearch() -{ - listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex()); -} - -void FlamePage::onSelectionChanged(QModelIndex first, QModelIndex second) -{ - ui->versionSelectionBox->clear(); - - if(!first.isValid()) - { - if(isOpened) - { - dialog->setSuggestedPack(); - } - return; - } - - current = listModel->data(first, Qt::UserRole).value(); - QString text = ""; - QString name = current.name; - - if (current.websiteUrl.isEmpty()) - text = name; - else - text = "" + name + ""; - if (!current.authors.empty()) { - auto authorToStr = [](Flame::ModpackAuthor & author) { - if(author.url.isEmpty()) { - return author.name; - } - return QString("%2").arg(author.url, author.name); - }; - QStringList authorStrs; - for(auto & author: current.authors) { - authorStrs.push_back(authorToStr(author)); - } - text += "
" + tr(" by ") + authorStrs.join(", "); - } - text += "

"; - - ui->packDescription->setHtml(text + current.description); - - if (current.versionsLoaded == false) - { - qDebug() << "Loading flame modpack versions"; - NetJob *netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network()); - std::shared_ptr response = std::make_shared(); - 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] - { - QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if(parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from CurseForge at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *response; - return; - } - QJsonArray arr = doc.array(); - try - { - Flame::loadIndexedPackVersions(current, arr); - } - catch(const JSONValidationError &e) - { - qDebug() << *response; - qWarning() << "Error while reading flame modpack version: " << e.cause(); - } - - for(auto version : current.versions) { - ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl)); - } - - suggestCurrent(); - }); - netJob->start(); - } - else - { - for(auto version : current.versions) { - ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl)); - } - - suggestCurrent(); - } -} - -void FlamePage::suggestCurrent() -{ - if(!isOpened) - { - return; - } - - if (selectedVersion.isEmpty()) - { - dialog->setSuggestedPack(); - return; - } - - dialog->setSuggestedPack(current.name, new InstanceImportTask(selectedVersion)); - QString editedLogoName; - editedLogoName = "curseforge_" + current.logoName.section(".", 0, 0); - listModel->getLogo(current.logoName, current.logoUrl, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo, editedLogoName); - }); -} - -void FlamePage::onVersionSelectionChanged(QString data) -{ - if(data.isNull() || data.isEmpty()) - { - selectedVersion = ""; - return; - } - selectedVersion = ui->versionSelectionBox->currentData().toString(); - suggestCurrent(); -} diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h deleted file mode 100644 index 5cfe21dc..00000000 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ /dev/null @@ -1,80 +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 - -#include "ui/pages/BasePage.h" -#include -#include "tasks/Task.h" -#include - -namespace Ui -{ -class FlamePage; -} - -class NewInstanceDialog; - -namespace Flame { - class ListModel; -} - -class FlamePage : public QWidget, public BasePage -{ - Q_OBJECT - -public: - explicit FlamePage(NewInstanceDialog* dialog, QWidget *parent = 0); - virtual ~FlamePage(); - virtual QString displayName() const override - { - return tr("CurseForge"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("flame"); - } - virtual QString id() const override - { - return "flame"; - } - virtual QString helpPage() const override - { - return "Flame-platform"; - } - virtual bool shouldDisplay() const override; - - void openedImpl() override; - - bool eventFilter(QObject * watched, QEvent * event) override; - -private: - void suggestCurrent(); - -private slots: - void triggerSearch(); - void onSelectionChanged(QModelIndex first, QModelIndex second); - void onVersionSelectionChanged(QString data); - -private: - Ui::FlamePage *ui = nullptr; - NewInstanceDialog* dialog = nullptr; - Flame::ListModel* listModel = nullptr; - Flame::IndexedPack current; - - QString selectedVersion; -}; diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.ui b/launcher/ui/pages/modplatform/flame/FlamePage.ui deleted file mode 100644 index 9723815a..00000000 --- a/launcher/ui/pages/modplatform/flame/FlamePage.ui +++ /dev/null @@ -1,90 +0,0 @@ - - - FlamePage - - - - 0 - 0 - 837 - 685 - - - - - - - - - - 48 - 48 - - - - Qt::ScrollBarAlwaysOff - - - true - - - - - - - true - - - true - - - - - - - - - - - - - - Version selected: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - Search - - - - - - - Search and filter ... - - - - - - - searchEdit - searchButton - packView - packDescription - sortByBox - versionSelectionBox - - - - diff --git a/launcher/ui/pages/modplatform/modpacksch/CursePage.cpp b/launcher/ui/pages/modplatform/modpacksch/CursePage.cpp deleted file mode 100644 index 8b2a3d29..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/CursePage.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2020-2021 Jamie Mansfield - * Copyright 2021 Philip T - * - * 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 "CursePage.h" -#include "ui_CursePage.h" - -#include - -#include "ui/dialogs/NewInstanceDialog.h" -#include "modplatform/modpacksch/FTBPackInstallTask.h" - -#include "HoeDown.h" - -CursePage::CursePage(NewInstanceDialog* dialog, QWidget *parent) - : QWidget(parent), ui(new Ui::CursePage), dialog(dialog) -{ - ui->setupUi(this); - connect(ui->searchButton, &QPushButton::clicked, this, &CursePage::triggerSearch); - - filterModel = new ModpacksCH::FilterModel(this); - listModel = new ModpacksCH::ListModel(this); - filterModel->setSourceModel(listModel); - ui->packView->setModel(filterModel); - ui->packView->setSortingEnabled(true); - ui->packView->header()->hide(); - ui->packView->setIndentation(0); - - ui->searchEdit->installEventFilter(this); - - ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); - - for(int i = 0; i < filterModel->getAvailableSortings().size(); i++) - { - ui->sortByBox->addItem(filterModel->getAvailableSortings().keys().at(i)); - } - ui->sortByBox->setCurrentText(filterModel->translateCurrentSorting()); - - connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &CursePage::onSortingSelectionChanged); - connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &CursePage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &CursePage::onVersionSelectionChanged); -} - -CursePage::~CursePage() -{ - delete ui; -} - -bool CursePage::eventFilter(QObject* watched, QEvent* event) -{ - if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) { - QKeyEvent* keyEvent = static_cast(event); - if (keyEvent->key() == Qt::Key_Return) { - triggerSearch(); - keyEvent->accept(); - return true; - } - } - return QWidget::eventFilter(watched, event); -} - -bool CursePage::shouldDisplay() const -{ - return true; -} - -void CursePage::openedImpl() -{ - if(!initialised) - { - initialised = true; - } - - suggestCurrent(); -} - -void CursePage::suggestCurrent() -{ - if(!isOpened) - { - return; - } - - if (selectedVersion.isEmpty()) - { - dialog->setSuggestedPack(); - return; - } - - auto & selectedPack = selected; - dialog->setSuggestedPack(selectedVersion, new ModpacksCH::PackInstallTask(selectedPack, selectedVersion, selected.packType)); - for(auto art : selectedPack.art) { - if(art.type == "square") { - QString editedLogoName; - editedLogoName = selectedPack.name; - - listModel->getLogo(selectedPack.name, art.url, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo + ".small", editedLogoName); - }); - } - } -} - -void CursePage::triggerSearch() -{ - listModel->requestCurse(ui->searchEdit->text()); -} - -void CursePage::onSortingSelectionChanged(QString data) -{ - auto toSet = filterModel->getAvailableSortings().value(data); - filterModel->setSorting(toSet); -} - -void CursePage::onSelectionChanged(QModelIndex first, QModelIndex second) -{ - ui->versionSelectionBox->clear(); - - if(!first.isValid()) - { - if(isOpened) - { - dialog->setSuggestedPack(); - } - return; - } - - selected = filterModel->data(first, Qt::UserRole).value(); - auto & selectedPack = selected; - - HoeDown hoedown; - QString output = hoedown.process(selectedPack.description.toUtf8()); - ui->packDescription->setHtml(output); - - // reverse foreach, so that the newest versions are first - for (auto i = selectedPack.versions.size(); i--;) { - ui->versionSelectionBox->addItem(selectedPack.versions.at(i).name); - } - - suggestCurrent(); -} - -void CursePage::onVersionSelectionChanged(QString data) -{ - if(data.isNull() || data.isEmpty()) - { - selectedVersion = ""; - return; - } - - selectedVersion = data; - suggestCurrent(); -} diff --git a/launcher/ui/pages/modplatform/modpacksch/CursePage.h b/launcher/ui/pages/modplatform/modpacksch/CursePage.h deleted file mode 100644 index e1f27b0d..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/CursePage.h +++ /dev/null @@ -1,83 +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 "MCHFilterModel.h" -#include "MCHListModel.h" - -#include - -#include "Application.h" -#include "ui/pages/BasePage.h" -#include "tasks/Task.h" - -namespace Ui -{ - class CursePage; -} - -class NewInstanceDialog; - -class CursePage : public QWidget, public BasePage -{ -Q_OBJECT - -public: - explicit CursePage(NewInstanceDialog* dialog, QWidget *parent = 0); - virtual ~CursePage(); - virtual QString displayName() const override - { - return tr("CurseForge"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("flame"); - } - virtual QString id() const override - { - return "flame"; - } - virtual QString helpPage() const override - { - return "Flame-platform"; - } - virtual bool shouldDisplay() const override; - - void openedImpl() override; - - bool eventFilter(QObject * watched, QEvent * event) override; - -private: - void suggestCurrent(); - -private slots: - void triggerSearch(); - - void onSortingSelectionChanged(QString data); - void onSelectionChanged(QModelIndex first, QModelIndex second); - void onVersionSelectionChanged(QString data); - -private: - Ui::CursePage *ui = nullptr; - NewInstanceDialog* dialog = nullptr; - ModpacksCH::ListModel* listModel = nullptr; - ModpacksCH::FilterModel* filterModel = nullptr; - - ModpacksCH::Modpack selected; - QString selectedVersion; - - bool initialised { false }; -}; diff --git a/launcher/ui/pages/modplatform/modpacksch/CursePage.ui b/launcher/ui/pages/modplatform/modpacksch/CursePage.ui deleted file mode 100644 index 671bd9dc..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/CursePage.ui +++ /dev/null @@ -1,86 +0,0 @@ - - - CursePage - - - - 0 - 0 - 875 - 745 - - - - - - - Search... - - - true - - - - - - - Search - - - - - - - - - true - - - - 48 - 48 - - - - - - - - true - - - true - - - - - - - - - - - - - - Version selected: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - searchEdit - versionSelectionBox - - - - diff --git a/launcher/ui/pages/modplatform/modpacksch/FtbPage.cpp b/launcher/ui/pages/modplatform/modpacksch/FtbPage.cpp deleted file mode 100644 index 689958e2..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/FtbPage.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2020-2021 Jamie Mansfield - * Copyright 2021 Philip T - * - * 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 "FtbPage.h" -#include "ui_FtbPage.h" - -#include - -#include "ui/dialogs/NewInstanceDialog.h" -#include "modplatform/modpacksch/FTBPackInstallTask.h" - -#include "HoeDown.h" - -FtbPage::FtbPage(NewInstanceDialog* dialog, QWidget *parent) - : QWidget(parent), ui(new Ui::FtbPage), dialog(dialog) -{ - ui->setupUi(this); - - filterModel = new ModpacksCH::FilterModel(this); - listModel = new ModpacksCH::ListModel(this); - filterModel->setSourceModel(listModel); - ui->packView->setModel(filterModel); - ui->packView->setSortingEnabled(true); - ui->packView->header()->hide(); - ui->packView->setIndentation(0); - - ui->searchEdit->installEventFilter(this); - - ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); - - for(int i = 0; i < filterModel->getAvailableSortings().size(); i++) - { - ui->sortByBox->addItem(filterModel->getAvailableSortings().keys().at(i)); - } - ui->sortByBox->setCurrentText(filterModel->translateCurrentSorting()); - - connect(ui->searchEdit, &QLineEdit::textChanged, this, &FtbPage::triggerSearch); - connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &FtbPage::onSortingSelectionChanged); - connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FtbPage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FtbPage::onVersionSelectionChanged); -} - -FtbPage::~FtbPage() -{ - delete ui; -} - -bool FtbPage::eventFilter(QObject* watched, QEvent* event) -{ - if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) { - QKeyEvent* keyEvent = static_cast(event); - if (keyEvent->key() == Qt::Key_Return) { - triggerSearch(); - keyEvent->accept(); - return true; - } - } - return QWidget::eventFilter(watched, event); -} - -bool FtbPage::shouldDisplay() const -{ - return true; -} - -void FtbPage::openedImpl() -{ - if(!initialised) - { - listModel->request(); - initialised = true; - } - - suggestCurrent(); -} - -void FtbPage::suggestCurrent() -{ - if(!isOpened) - { - return; - } - - if (selectedVersion.isEmpty()) - { - dialog->setSuggestedPack(); - return; - } - - auto & selectedPack = selected; - dialog->setSuggestedPack(selected.name + " " + selectedVersion, new ModpacksCH::PackInstallTask(selectedPack, selectedVersion, selected.packType)); - for(auto art : selectedPack.art) { - if(art.type == "square") { - QString editedLogoName; - editedLogoName = selectedPack.name; - - listModel->getLogo(selectedPack.name, art.url, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo + ".small", editedLogoName); - }); - } - } -} - -void FtbPage::triggerSearch() -{ - filterModel->setSearchTerm(ui->searchEdit->text()); -} - -void FtbPage::onSortingSelectionChanged(QString data) -{ - auto toSet = filterModel->getAvailableSortings().value(data); - filterModel->setSorting(toSet); -} - -void FtbPage::onSelectionChanged(QModelIndex first, QModelIndex second) -{ - ui->versionSelectionBox->clear(); - - if(!first.isValid()) - { - if(isOpened) - { - dialog->setSuggestedPack(); - } - return; - } - - selected = filterModel->data(first, Qt::UserRole).value(); - auto & selectedPack = selected; - - HoeDown hoedown; - QString output = hoedown.process(selectedPack.description.toUtf8()); - ui->packDescription->setHtml(output); - - // reverse foreach, so that the newest versions are first - for (auto i = selectedPack.versions.size(); i--;) { - ui->versionSelectionBox->addItem(selectedPack.versions.at(i).name); - } - - suggestCurrent(); -} - -void FtbPage::onVersionSelectionChanged(QString data) -{ - if(data.isNull() || data.isEmpty()) - { - selectedVersion = ""; - return; - } - - selectedVersion = data; - suggestCurrent(); -} diff --git a/launcher/ui/pages/modplatform/modpacksch/FtbPage.h b/launcher/ui/pages/modplatform/modpacksch/FtbPage.h deleted file mode 100644 index d0ac10fb..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/FtbPage.h +++ /dev/null @@ -1,83 +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 "MCHFilterModel.h" -#include "MCHListModel.h" - -#include - -#include "Application.h" -#include "ui/pages/BasePage.h" -#include "tasks/Task.h" - -namespace Ui -{ - class FtbPage; -} - -class NewInstanceDialog; - -class FtbPage : public QWidget, public BasePage -{ -Q_OBJECT - -public: - explicit FtbPage(NewInstanceDialog* dialog, QWidget *parent = 0); - virtual ~FtbPage(); - virtual QString displayName() const override - { - return tr("FTB"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("ftb_logo"); - } - virtual QString id() const override - { - return "ftb"; - } - virtual QString helpPage() const override - { - return "FTB-platform"; - } - virtual bool shouldDisplay() const override; - - void openedImpl() override; - - bool eventFilter(QObject * watched, QEvent * event) override; - -private: - void suggestCurrent(); - -private slots: - void triggerSearch(); - - void onSortingSelectionChanged(QString data); - void onSelectionChanged(QModelIndex first, QModelIndex second); - void onVersionSelectionChanged(QString data); - -private: - Ui::FtbPage *ui = nullptr; - NewInstanceDialog* dialog = nullptr; - ModpacksCH::ListModel* listModel = nullptr; - ModpacksCH::FilterModel* filterModel = nullptr; - - ModpacksCH::Modpack selected; - QString selectedVersion; - - bool initialised { false }; -}; diff --git a/launcher/ui/pages/modplatform/modpacksch/FtbPage.ui b/launcher/ui/pages/modplatform/modpacksch/FtbPage.ui deleted file mode 100644 index e9c783e3..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/FtbPage.ui +++ /dev/null @@ -1,79 +0,0 @@ - - - FtbPage - - - - 0 - 0 - 875 - 745 - - - - - - - - - - - - Version selected: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - Search and filter ... - - - true - - - - - - - - - true - - - - 48 - 48 - - - - - - - - true - - - true - - - - - - - - - searchEdit - versionSelectionBox - - - - diff --git a/launcher/ui/pages/modplatform/modpacksch/MCHFilterModel.cpp b/launcher/ui/pages/modplatform/modpacksch/MCHFilterModel.cpp deleted file mode 100644 index 13ce06b5..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/MCHFilterModel.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2020-2021 Jamie Mansfield - * - * 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 "MCHFilterModel.h" - -#include - -#include "modplatform/modpacksch/FTBPackManifest.h" -#include - -namespace ModpacksCH { - -FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent) -{ - currentSorting = Sorting::ByPlays; - sortings.insert(tr("Sort by plays"), Sorting::ByPlays); - sortings.insert(tr("Sort by installs"), Sorting::ByInstalls); - sortings.insert(tr("Sort by name"), Sorting::ByName); -} - -const QMap FilterModel::getAvailableSortings() -{ - return sortings; -} - -QString FilterModel::translateCurrentSorting() -{ - return sortings.key(currentSorting); -} - -void FilterModel::setSorting(Sorting sorting) -{ - currentSorting = sorting; - invalidate(); -} - -FilterModel::Sorting FilterModel::getCurrentSorting() -{ - return currentSorting; -} - -void FilterModel::setSearchTerm(const QString& term) -{ - searchTerm = term.trimmed(); - invalidate(); -} - -bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const -{ - if (searchTerm.isEmpty()) { - return true; - } - - auto index = sourceModel()->index(sourceRow, 0, sourceParent); - auto pack = sourceModel()->data(index, Qt::UserRole).value(); - return pack.name.contains(searchTerm, Qt::CaseInsensitive); -} - -bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const -{ - ModpacksCH::Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value(); - ModpacksCH::Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value(); - - if (currentSorting == ByPlays) { - return leftPack.plays < rightPack.plays; - } - else if (currentSorting == ByInstalls) { - return leftPack.installs < rightPack.installs; - } - else if (currentSorting == ByName) { - return Strings::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0; - } - - // Invalid sorting set, somehow... - qWarning() << "Invalid sorting set!"; - return true; -} - -} diff --git a/launcher/ui/pages/modplatform/modpacksch/MCHFilterModel.h b/launcher/ui/pages/modplatform/modpacksch/MCHFilterModel.h deleted file mode 100644 index 12014c3a..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/MCHFilterModel.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2020-2021 Jamie Mansfield - * - * 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 - -namespace ModpacksCH { - -class FilterModel : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - FilterModel(QObject* parent = Q_NULLPTR); - enum Sorting { - ByPlays, - ByInstalls, - ByName, - }; - const QMap getAvailableSortings(); - QString translateCurrentSorting(); - void setSorting(Sorting sorting); - Sorting getCurrentSorting(); - void setSearchTerm(const QString& term); - -protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; - -private: - QMap sortings; - Sorting currentSorting; - QString searchTerm { "" }; - -}; - -} diff --git a/launcher/ui/pages/modplatform/modpacksch/MCHListModel.cpp b/launcher/ui/pages/modplatform/modpacksch/MCHListModel.cpp deleted file mode 100644 index e876508d..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/MCHListModel.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright 2020-2021 Jamie Mansfield - * - * 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 "MCHListModel.h" - -#include "BuildConfig.h" -#include "Application.h" -#include "Json.h" - -#include -#include - -namespace ModpacksCH { - -ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) -{ -} - -ListModel::~ListModel() -{ -} - -int ListModel::rowCount(const QModelIndex &parent) const -{ - return modpacks.size(); -} - -int ListModel::columnCount(const QModelIndex &parent) const -{ - return 1; -} - -QVariant ListModel::data(const QModelIndex &index, int role) const -{ - int pos = index.row(); - if(pos >= modpacks.size() || pos < 0 || !index.isValid()) - { - return QString("INVALID INDEX %1").arg(pos); - } - - auto &pack = modpacks.at(pos); - if(role == Qt::DisplayRole) - { - return pack.name; - } - else if (role == Qt::ToolTipRole) - { - return pack.synopsis; - } - else if(role == Qt::DecorationRole) - { - QIcon placeholder = APPLICATION->getThemedIcon("screenshot-placeholder"); - - auto iter = m_logoMap.find(pack.name); - if (iter != m_logoMap.end()) { - auto & logo = *iter; - if(!logo.result.isNull()) { - return logo.result; - } - return placeholder; - } - - for(auto art : pack.art) { - if(art.type == "square") { - ((ListModel *)this)->requestLogo(pack.name, art.url); - } - } - return placeholder; - } - else if(role == Qt::UserRole) - { - QVariant v; - v.setValue(pack); - return v; - } - - return QVariant(); -} - -void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback) -{ - if(m_logoMap.contains(logo)) - { - callback(APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); - } - else - { - requestLogo(logo, logoUrl); - } -} - -void ListModel::request() -{ - if(jobPtr) { - jobPtr->abort(); - jobPtr.reset(); - } - - requestedPackType = PackType::FTB; - - beginResetModel(); - modpacks.clear(); - endResetModel(); - - auto *netJob = new NetJob("Ftb::Request", APPLICATION->network()); - auto url = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/modpack/all"); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response)); - jobPtr = netJob; - jobPtr->start(); - - QObject::connect(netJob, &NetJob::succeeded, this, &ListModel::requestFinished); - QObject::connect(netJob, &NetJob::failed, this, &ListModel::requestFailed); -} - -void ListModel::requestCurse(const QString & searchTerm) { - - if(jobPtr) { - jobPtr->abort(); - jobPtr.reset(); - } - - requestedPackType = PackType::CurseForge; - - beginResetModel(); - modpacks.clear(); - endResetModel(); - - auto *netJob = new NetJob("Ftb::RequestCurse", APPLICATION->network()); - auto url = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/modpack/search/25?term=" + searchTerm); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response)); - jobPtr = netJob; - jobPtr->start(); - - QObject::connect(netJob, &NetJob::succeeded, this, &ListModel::requestFinished); - QObject::connect(netJob, &NetJob::failed, this, &ListModel::requestFailed); -} - -void ListModel::requestFinished() -{ - jobPtr.reset(); - remainingPacks.clear(); - - QJsonParseError parse_error {}; - QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); - if(parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from ModpacksCH at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << response; - return; - } - qDebug() << response; - - if(requestedPackType == PackType::FTB) { - auto packs = doc.object().value("packs").toArray(); - for(auto pack : packs) { - auto packId = pack.toInt(); - remainingPacks.append({ModpacksCH::PackType::FTB, packId}); - } - } - - if(requestedPackType == PackType::CurseForge) { - auto cfpacks = doc.object().value("curseforge").toArray(); - for(auto pack : cfpacks) { - auto packId = pack.toInt(); - remainingPacks.append({ModpacksCH::PackType::CurseForge, packId}); - } - } - - if(!remainingPacks.isEmpty()) { - currentPack = remainingPacks.at(0); - requestPack(); - } -} - -void ListModel::requestFailed(QString reason) -{ - jobPtr.reset(); - remainingPacks.clear(); -} - -void ListModel::requestPack() -{ - auto *netJob = new NetJob("Ftb::Search", APPLICATION->network()); - QString requestUrl; - switch(currentPack.type) { - case ModpacksCH::PackType::FTB: { - requestUrl = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/modpack/%1").arg(currentPack.identifier); - break; - } - case ModpacksCH::PackType::CurseForge: { - requestUrl = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/curseforge/%1").arg(currentPack.identifier); - } - } - netJob->addNetAction(Net::Download::makeByteArray(QUrl(requestUrl), &response)); - jobPtr = netJob; - jobPtr->start(); - - QObject::connect(netJob, &NetJob::succeeded, this, &ListModel::packRequestFinished); - QObject::connect(netJob, &NetJob::failed, this, &ListModel::packRequestFailed); -} - -void ListModel::packRequestFinished() -{ - jobPtr.reset(); - auto type = currentPack.type; - remainingPacks.removeOne(currentPack); - - QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); - - if(parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from ModpacksCH at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << response; - return; - } - - auto obj = doc.object(); - - Modpack pack; - try - { - ModpacksCH::loadModpack(pack, obj); - pack.packType = type; - if(type == ModpacksCH::PackType::CurseForge) { - std::reverse(pack.versions.begin(), pack.versions.end()); - } - } - catch (const JSONValidationError &e) - { - qDebug() << QString::fromUtf8(response); - qWarning() << "Error while reading pack manifest from ModpacksCH: " << e.cause(); - return; - } - - // Since there is no guarantee that packs have a version, this will just - // ignore those "dud" packs. - if (pack.versions.empty()) - { - qWarning() << "ModpacksCH Pack " << pack.id << " ignored. reason: lacking any versions"; - } - else - { - beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size()); - modpacks.append(pack); - endInsertRows(); - } - - if(!remainingPacks.isEmpty()) { - currentPack = remainingPacks.at(0); - requestPack(); - } -} - -void ListModel::packRequestFailed(QString reason) -{ - jobPtr.reset(); - remainingPacks.removeOne(currentPack); -} - -void ListModel::logoLoaded(QString logo, bool stale) -{ - auto & logoObj = m_logoMap[logo]; - logoObj.downloadJob.reset(); - QString smallPath = logoObj.fullpath + ".small"; - - QFileInfo smallInfo(smallPath); - - if(stale || !smallInfo.exists()) { - QImage image(logoObj.fullpath); - if (image.isNull()) - { - logoObj.failed = true; - return; - } - QImage small; - if (image.width() > image.height()) { - small = image.scaledToWidth(512).scaledToWidth(256, Qt::SmoothTransformation); - } - else { - small = image.scaledToHeight(512).scaledToHeight(256, Qt::SmoothTransformation); - } - QPoint offset((256 - small.width()) / 2, (256 - small.height()) / 2); - QImage square(QSize(256, 256), QImage::Format_ARGB32); - square.fill(Qt::transparent); - - QPainter painter(&square); - painter.drawImage(offset, small); - painter.end(); - - square.save(logoObj.fullpath + ".small", "PNG"); - } - - logoObj.result = QIcon(logoObj.fullpath + ".small"); - for(int i = 0; i < modpacks.size(); i++) { - if(modpacks[i].name == logo) { - emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole}); - } - } -} - -void ListModel::logoFailed(QString logo) -{ - m_logoMap[logo].failed = true; - m_logoMap[logo].downloadJob.reset(); -} - -void ListModel::requestLogo(QString logo, QString url) -{ - if(m_logoMap.contains(logo)) { - return; - } - - MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", QString("logos/%1").arg(logo.section(".", 0, 0))); - - bool stale = entry->isStale(); - - auto *job = new NetJob(QString("ModpacksCH Icon Download %1").arg(logo), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); - - auto fullPath = entry->getFullPath(); - QObject::connect(job, &NetJob::finished, this, [this, logo, fullPath, stale] - { - logoLoaded(logo, stale); - }); - - QObject::connect(job, &NetJob::failed, this, [this, logo] - { - logoFailed(logo); - }); - - auto &newLogoEntry = m_logoMap[logo]; - newLogoEntry.downloadJob = job; - newLogoEntry.fullpath = fullPath; - job->start(); -} - -} diff --git a/launcher/ui/pages/modplatform/modpacksch/MCHListModel.h b/launcher/ui/pages/modplatform/modpacksch/MCHListModel.h deleted file mode 100644 index 899333cf..00000000 --- a/launcher/ui/pages/modplatform/modpacksch/MCHListModel.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2020-2021 Jamie Mansfield - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -#include "modplatform/modpacksch/FTBPackManifest.h" -#include "modplatform/modpacksch/MCHPackType.h" -#include "net/NetJob.h" -#include - -namespace ModpacksCH { - -struct Logo { - QString fullpath; - NetJob::Ptr downloadJob; - QIcon result; - bool failed = false; -}; - -typedef QMap LogoMap; -typedef std::function LogoCallback; - -struct PackCoord { - bool operator==(const PackCoord& other) { - return type == other.type && identifier == other.identifier; - } - PackType type; - int identifier; -}; - -class ListModel : public QAbstractListModel -{ - Q_OBJECT - -public: - ListModel(QObject *parent); - virtual ~ListModel(); - - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - - void request(); - void requestCurse(const QString & searchTerm); - - void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback); - -private slots: - void requestFinished(); - void requestFailed(QString reason); - - void requestPack(); - void packRequestFinished(); - void packRequestFailed(QString reason); - - void logoFailed(QString logo); - void logoLoaded(QString logo, bool stale); - -private: - void requestLogo(QString file, QString url); - -private: - PackType requestedPackType = PackType::FTB; - QList modpacks; - LogoMap m_logoMap; - - NetJob::Ptr jobPtr; - PackCoord currentPack; - QList remainingPacks; - QByteArray response; -}; - -}