From be963764eaa5e3721cc2d96598d10d22bdae9000 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 25 Mar 2025 00:09:15 +0200 Subject: [PATCH 001/118] propagate side as enum instead of Qstring Signed-off-by: Trial97 --- launcher/minecraft/mod/MetadataHandler.h | 27 +-------- launcher/minecraft/mod/Mod.cpp | 4 +- launcher/modplatform/ModIndex.cpp | 25 +++++++++ launcher/modplatform/ModIndex.h | 11 +++- launcher/modplatform/ResourceAPI.h | 2 +- launcher/modplatform/flame/FlameModIndex.cpp | 10 ++-- launcher/modplatform/modrinth/ModrinthAPI.h | 22 ++++---- .../modrinth/ModrinthPackExportTask.cpp | 3 +- .../modrinth/ModrinthPackExportTask.h | 3 +- .../modrinth/ModrinthPackIndex.cpp | 6 +- launcher/modplatform/packwiz/Packwiz.cpp | 55 +------------------ launcher/modplatform/packwiz/Packwiz.h | 17 +----- launcher/ui/pages/modplatform/ModModel.cpp | 6 +- .../ui/pages/modplatform/flame/FlameModel.cpp | 5 +- .../modplatform/modrinth/ModrinthModel.cpp | 5 +- launcher/ui/widgets/ModFilterWidget.cpp | 12 ++-- launcher/ui/widgets/ModFilterWidget.h | 2 +- tests/Packwiz_test.cpp | 5 +- 18 files changed, 89 insertions(+), 131 deletions(-) diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h index 0b8cb124d..5f12348ae 100644 --- a/launcher/minecraft/mod/MetadataHandler.h +++ b/launcher/minecraft/mod/MetadataHandler.h @@ -19,27 +19,16 @@ #pragma once -#include - #include "modplatform/packwiz/Packwiz.h" -// launcher/minecraft/mod/Mod.h -class Mod; - namespace Metadata { using ModStruct = Packwiz::V1::Mod; -using ModSide = Packwiz::V1::Side; -inline auto create(const QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> ModStruct +inline ModStruct create(const QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) { return Packwiz::V1::createModFormat(index_dir, mod_pack, mod_version); } -inline auto create(const QDir& index_dir, Mod& internal_mod, QString mod_slug) -> ModStruct -{ - return Packwiz::V1::createModFormat(index_dir, internal_mod, std::move(mod_slug)); -} - inline void update(const QDir& index_dir, ModStruct& mod) { Packwiz::V1::updateModIndex(index_dir, mod); @@ -50,24 +39,14 @@ inline void remove(const QDir& index_dir, QString mod_slug) Packwiz::V1::deleteModIndex(index_dir, mod_slug); } -inline void remove(const QDir& index_dir, QVariant& mod_id) -{ - Packwiz::V1::deleteModIndex(index_dir, mod_id); -} - -inline auto get(const QDir& index_dir, QString mod_slug) -> ModStruct +inline ModStruct get(const QDir& index_dir, QString mod_slug) { return Packwiz::V1::getIndexForMod(index_dir, std::move(mod_slug)); } -inline auto get(const QDir& index_dir, QVariant& mod_id) -> ModStruct +inline ModStruct get(const QDir& index_dir, QVariant& mod_id) { return Packwiz::V1::getIndexForMod(index_dir, mod_id); } -inline auto modSideToString(ModSide side) -> QString -{ - return Packwiz::V1::sideToString(side); -} - }; // namespace Metadata diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index 99fc39ce0..e9ca2e682 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -179,9 +179,9 @@ auto Mod::loaders() const -> QString auto Mod::side() const -> QString { if (metadata()) - return Metadata::modSideToString(metadata()->side); + return ModPlatform::SideUtils::toString(metadata()->side); - return Metadata::modSideToString(Metadata::ModSide::UniversalSide); + return ModPlatform::SideUtils::toString(ModPlatform::Side::UniversalSide); } auto Mod::mcVersions() const -> QString diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 380ff660f..e18ccaefa 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -152,4 +152,29 @@ auto getModLoaderFromString(QString type) -> ModLoaderType return {}; } +QString SideUtils::toString(Side side) +{ + switch (side) { + case Side::ClientSide: + return "client"; + case Side::ServerSide: + return "server"; + case Side::UniversalSide: + return "both"; + case Side::NoSide: + break; + } + return {}; +} + +Side SideUtils::fromString(QString side) +{ + if (side == "client") + return Side::ClientSide; + if (side == "server") + return Side::ServerSide; + if (side == "both") + return Side::UniversalSide; + return Side::UniversalSide; +} } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index ad2503ea7..cfe4eba75 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -47,6 +47,13 @@ enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK, MODPACK, DATA_PACK }; enum class DependencyType { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE, UNKNOWN }; +enum class Side { NoSide = 0, ClientSide = 1 << 0, ServerSide = 1 << 1, UniversalSide = ClientSide | ServerSide }; + +namespace SideUtils { +QString toString(Side side); +Side fromString(QString side); +} // namespace SideUtils + namespace ProviderCapabilities { const char* name(ResourceProvider); QString readableName(ResourceProvider); @@ -114,7 +121,7 @@ struct IndexedVersion { bool is_preferred = true; QString changelog; QList dependencies; - QString side; // this is for flame API + Side side; // this is for flame API // For internal use, not provided by APIs bool is_currently_selected = false; @@ -145,7 +152,7 @@ struct IndexedPack { QString logoName; QString logoUrl; QString websiteUrl; - QString side; + Side side; bool versionsLoaded = false; QList versions; diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 62a1ff199..bd6b90227 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -74,7 +74,7 @@ class ResourceAPI { std::optional sorting; std::optional loaders; std::optional> versions; - std::optional side; + std::optional side; std::optional categoryIds; bool openSource; }; diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index c1b9e67af..660dc159c 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -4,6 +4,7 @@ #include "Json.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" +#include "modplatform/ModIndex.h" #include "modplatform/flame/FlameAPI.h" static FlameAPI api; @@ -110,6 +111,7 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> if (str.contains('.')) file.mcVersion.append(str); + file.side = ModPlatform::Side::NoSide; if (auto loader = str.toLower(); loader == "neoforge") file.loaders |= ModPlatform::NeoForge; else if (loader == "forge") @@ -123,10 +125,10 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> else if (loader == "quilt") file.loaders |= ModPlatform::Quilt; else if (loader == "server" || loader == "client") { - if (file.side.isEmpty()) - file.side = loader; - else if (file.side != loader) - file.side = "both"; + if (file.side == ModPlatform::Side::NoSide) + file.side = ModPlatform::SideUtils::fromString(loader); + else if (file.side != ModPlatform::SideUtils::fromString(loader)) + file.side = ModPlatform::Side::UniversalSide; } } diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 17b23723b..7c2592256 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -69,18 +69,20 @@ class ModrinthAPI : public NetworkResourceAPI { return l.join(','); } - static auto getSideFilters(QString side) -> const QString + static QString getSideFilters(ModPlatform::Side side) { - if (side.isEmpty()) { - return {}; + switch (side) { + case ModPlatform::Side::ClientSide: + return QString("\"client_side:required\",\"client_side:optional\"],[\"server_side:optional\",\"server_side:unsupported\""); + case ModPlatform::Side::ServerSide: + return QString("\"server_side:required\",\"server_side:optional\"],[\"client_side:optional\",\"client_side:unsupported\""); + case ModPlatform::Side::UniversalSide: + return QString("\"client_side:required\"],[\"server_side:required\""); + case ModPlatform::Side::NoSide: + // fallthrough + default: + return {}; } - if (side == "both") - return QString("\"client_side:required\"],[\"server_side:required\""); - if (side == "client") - return QString("\"client_side:required\",\"client_side:optional\"],[\"server_side:optional\",\"server_side:unsupported\""); - if (side == "server") - return QString("\"server_side:required\",\"server_side:optional\"],[\"client_side:optional\",\"client_side:unsupported\""); - return {}; } [[nodiscard]] static inline QString mapMCVersionFromModrinth(QString v) diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 4b19acd3f..9ee4101e6 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -28,6 +28,7 @@ #include "minecraft/PackProfile.h" #include "minecraft/mod/MetadataHandler.h" #include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" @@ -289,7 +290,7 @@ QByteArray ModrinthPackExportTask::generateIndex() // a server side mod does not imply that the mod does not work on the client // however, if a mrpack mod is marked as server-only it will not install on the client - if (iterator->side == Metadata::ModSide::ClientSide) + if (iterator->side == ModPlatform::Side::ClientSide) env["server"] = "unsupported"; fileOut["env"] = env; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index ec4730de5..f9b86bbd7 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -23,6 +23,7 @@ #include "BaseInstance.h" #include "MMCZip.h" #include "minecraft/MinecraftInstance.h" +#include "modplatform/ModIndex.h" #include "modplatform/modrinth/ModrinthAPI.h" #include "tasks/Task.h" @@ -45,7 +46,7 @@ class ModrinthPackExportTask : public Task { struct ResolvedFile { QString sha1, sha512, url; qint64 size; - Metadata::ModSide side; + ModPlatform::Side side; }; static const QStringList PREFIXES; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 744b058c0..42fda9df1 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -63,11 +63,11 @@ void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) auto server = shouldDownloadOnSide(Json::ensureString(obj, "server_side")); if (server && client) { - pack.side = "both"; + pack.side = ModPlatform::Side::UniversalSide; } else if (server) { - pack.side = "server"; + pack.side = ModPlatform::Side::ServerSide; } else if (client) { - pack.side = "client"; + pack.side = ModPlatform::Side::ClientSide; } // Modrinth can have more data than what's provided by the basic search :) diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index a3bb74399..0660d611c 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -28,7 +28,6 @@ #include "FileSystem.h" #include "StringUtils.h" -#include "minecraft/mod/Mod.h" #include "modplatform/ModIndex.h" #include @@ -113,7 +112,7 @@ auto V1::createModFormat([[maybe_unused]] const QDir& index_dir, mod.provider = mod_pack.provider; mod.file_id = mod_version.fileId; mod.project_id = mod_pack.addonId; - mod.side = stringToSide(mod_version.side.isEmpty() ? mod_pack.side : mod_version.side); + mod.side = mod_version.side == ModPlatform::Side::NoSide ? mod_pack.side : mod_version.side; mod.loaders = mod_version.loaders; mod.mcVersions = mod_version.mcVersion; mod.mcVersions.sort(); @@ -126,18 +125,6 @@ auto V1::createModFormat([[maybe_unused]] const QDir& index_dir, return mod; } -auto V1::createModFormat(const QDir& index_dir, [[maybe_unused]] ::Mod& internal_mod, QString slug) -> Mod -{ - // Try getting metadata if it exists - Mod mod{ getIndexForMod(index_dir, slug) }; - if (mod.isValid()) - return mod; - - qWarning() << QString("Tried to create mod metadata with a Mod without metadata!"); - - return {}; -} - void V1::updateModIndex(const QDir& index_dir, Mod& mod) { if (!mod.isValid()) { @@ -208,7 +195,7 @@ void V1::updateModIndex(const QDir& index_dir, Mod& mod) { auto tbl = toml::table{ { "name", mod.name.toStdString() }, { "filename", mod.filename.toStdString() }, - { "side", sideToString(mod.side).toStdString() }, + { "side", ModPlatform::SideUtils::toString(mod.side).toStdString() }, { "x-prismlauncher-loaders", loaders }, { "x-prismlauncher-mc-versions", mcVersions }, { "x-prismlauncher-release-type", mod.releaseType.toString().toStdString() }, @@ -249,18 +236,6 @@ void V1::deleteModIndex(const QDir& index_dir, QString& mod_slug) } } -void V1::deleteModIndex(const QDir& index_dir, QVariant& mod_id) -{ - for (auto& file_name : index_dir.entryList(QDir::Filter::Files)) { - auto mod = getIndexForMod(index_dir, file_name); - - if (mod.mod_id() == mod_id) { - deleteModIndex(index_dir, mod.name); - break; - } - } -} - auto V1::getIndexForMod(const QDir& index_dir, QString slug) -> Mod { Mod mod; @@ -296,7 +271,7 @@ auto V1::getIndexForMod(const QDir& index_dir, QString slug) -> Mod { // Basic info mod.name = stringEntry(table, "name"); mod.filename = stringEntry(table, "filename"); - mod.side = stringToSide(stringEntry(table, "side")); + mod.side = ModPlatform::SideUtils::fromString(stringEntry(table, "side")); mod.releaseType = ModPlatform::IndexedVersionType(table["x-prismlauncher-release-type"].value_or("")); if (auto loaders = table["x-prismlauncher-loaders"]; loaders && loaders.is_array()) { for (auto&& loader : *loaders.as_array()) { @@ -371,28 +346,4 @@ auto V1::getIndexForMod(const QDir& index_dir, QVariant& mod_id) -> Mod return {}; } -auto V1::sideToString(Side side) -> QString -{ - switch (side) { - case Side::ClientSide: - return "client"; - case Side::ServerSide: - return "server"; - case Side::UniversalSide: - return "both"; - } - return {}; -} - -auto V1::stringToSide(QString side) -> Side -{ - if (side == "client") - return Side::ClientSide; - if (side == "server") - return Side::ServerSide; - if (side == "both") - return Side::UniversalSide; - return Side::UniversalSide; -} - } // namespace Packwiz diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 44896e74c..ba9a0fe75 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -27,23 +27,18 @@ class QDir; -// Mod from launcher/minecraft/mod/Mod.h -class Mod; - namespace Packwiz { auto getRealIndexName(const QDir& index_dir, QString normalized_index_name, bool should_match = false) -> QString; class V1 { public: - enum class Side { ClientSide = 1 << 0, ServerSide = 1 << 1, UniversalSide = ClientSide | ServerSide }; - // can also represent other resources beside loader mods - but this is what packwiz calls it struct Mod { QString slug{}; QString name{}; QString filename{}; - Side side{ Side::UniversalSide }; + ModPlatform::Side side{ ModPlatform::Side::UniversalSide }; ModPlatform::ModLoaderTypes loaders; QStringList mcVersions; ModPlatform::IndexedVersionType releaseType; @@ -74,10 +69,6 @@ class V1 { * its common representation in the launcher, when downloading mods. * */ static auto createModFormat(const QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod; - /* Generates the object representing the information in a mod.pw.toml file via - * its common representation in the launcher, plus a necessary slug. - * */ - static auto createModFormat(const QDir& index_dir, ::Mod& internal_mod, QString slug) -> Mod; /* Updates the mod index for the provided mod. * This creates a new index if one does not exist already @@ -88,9 +79,6 @@ class V1 { /* Deletes the metadata for the mod with the given slug. If the metadata doesn't exist, it does nothing. */ static void deleteModIndex(const QDir& index_dir, QString& mod_slug); - /* Deletes the metadata for the mod with the given id. If the metadata doesn't exist, it does nothing. */ - static void deleteModIndex(const QDir& index_dir, QVariant& mod_id); - /* Gets the metadata for a mod with a particular file name. * If the mod doesn't have a metadata, it simply returns an empty Mod object. * */ @@ -100,9 +88,6 @@ class V1 { * If the mod doesn't have a metadata, it simply returns an empty Mod object. * */ static auto getIndexForMod(const QDir& index_dir, QVariant& mod_id) -> Mod; - - static auto sideToString(Side side) -> QString; - static auto stringToSide(QString side) -> Side; }; } // namespace Packwiz diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 6e98a88bc..32e6f2146 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -7,6 +7,7 @@ #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" #include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" #include #include @@ -101,9 +102,10 @@ QVariant ModModel::getInstalledPackVersion(ModPlatform::IndexedPack::Ptr pack) c return {}; } -bool checkSide(QString filter, QString value) +bool checkSide(ModPlatform::Side filter, ModPlatform::Side value) { - return filter.isEmpty() || value.isEmpty() || filter == "both" || value == "both" || filter == value; + return filter == ModPlatform::Side::NoSide || value == ModPlatform::Side::NoSide || filter == ModPlatform::Side::UniversalSide || + value == ModPlatform::Side::UniversalSide || filter == value; } bool ModModel::checkFilters(ModPlatform::IndexedPack::Ptr pack) diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index d501bf9f4..5f254597d 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -186,8 +186,9 @@ void ListModel::performPaginatedSearch() sort.index = currentSort + 1; auto netJob = makeShared("Flame::Search", APPLICATION->network()); - auto searchUrl = FlameAPI().getSearchURL({ ModPlatform::ResourceType::MODPACK, nextSearchOffset, currentSearchTerm, sort, - m_filter->loaders, m_filter->versions, "", m_filter->categoryIds, m_filter->openSource }); + auto searchUrl = + FlameAPI().getSearchURL({ ModPlatform::ResourceType::MODPACK, nextSearchOffset, currentSearchTerm, sort, m_filter->loaders, + m_filter->versions, ModPlatform::Side::NoSide, m_filter->categoryIds, m_filter->openSource }); netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl.value()), response)); jobPtr = netJob; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 4681b1a7f..ae8e05a6f 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -152,8 +152,9 @@ void ModpackListModel::performPaginatedSearch() } // TODO: Move to standalone API ResourceAPI::SortingMethod sort{}; sort.name = currentSort; - auto searchUrl = ModrinthAPI().getSearchURL({ ModPlatform::ResourceType::MODPACK, nextSearchOffset, currentSearchTerm, sort, - m_filter->loaders, m_filter->versions, "", m_filter->categoryIds, m_filter->openSource }); + auto searchUrl = + ModrinthAPI().getSearchURL({ ModPlatform::ResourceType::MODPACK, nextSearchOffset, currentSearchTerm, sort, m_filter->loaders, + m_filter->versions, ModPlatform::Side::NoSide, m_filter->categoryIds, m_filter->openSource }); auto netJob = makeShared("Modrinth::SearchModpack", APPLICATION->network()); netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl.value()), m_allResponse)); diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index 031ff0f94..6fbaf5944 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -218,7 +218,7 @@ void ModFilterWidget::prepareBasicFilter() m_filter->openSource = false; if (m_instance) { m_filter->hideInstalled = false; - m_filter->side = ""; // or "both" + m_filter->side = ModPlatform::Side::NoSide; // or "both" ModPlatform::ModLoaderTypes loaders; if (m_instance->settings()->get("OverrideModDownloadLoaders").toBool()) { for (auto loader : Json::toStringList(m_instance->settings()->get("ModDownloadLoaders").toString())) { @@ -287,16 +287,16 @@ void ModFilterWidget::onLoadersFilterChanged() void ModFilterWidget::onSideFilterChanged() { - QString side; + ModPlatform::Side side; if (ui->clientSide->isChecked() && !ui->serverSide->isChecked()) { - side = "client"; + side = ModPlatform::Side::ClientSide; } else if (!ui->clientSide->isChecked() && ui->serverSide->isChecked()) { - side = "server"; + side = ModPlatform::Side::ServerSide; } else if (ui->clientSide->isChecked() && ui->serverSide->isChecked()) { - side = "both"; + side = ModPlatform::Side::UniversalSide; } else { - side = ""; + side = ModPlatform::Side::NoSide; } m_filter_changed = side != m_filter->side; diff --git a/launcher/ui/widgets/ModFilterWidget.h b/launcher/ui/widgets/ModFilterWidget.h index 88f2593dd..be60ba70a 100644 --- a/launcher/ui/widgets/ModFilterWidget.h +++ b/launcher/ui/widgets/ModFilterWidget.h @@ -61,7 +61,7 @@ class ModFilterWidget : public QTabWidget { std::list versions; std::list releases; ModPlatform::ModLoaderTypes loaders; - QString side; + ModPlatform::Side side; bool hideInstalled; QStringList categoryIds; bool openSource; diff --git a/tests/Packwiz_test.cpp b/tests/Packwiz_test.cpp index e4abda9f9..1fcb1b9f9 100644 --- a/tests/Packwiz_test.cpp +++ b/tests/Packwiz_test.cpp @@ -19,6 +19,7 @@ #include #include +#include "modplatform/ModIndex.h" #include @@ -42,7 +43,7 @@ class PackwizTest : public QObject { QCOMPARE(metadata.name, "Borderless Mining"); QCOMPARE(metadata.filename, "borderless-mining-1.1.1+1.18.jar"); - QCOMPARE(metadata.side, Packwiz::V1::Side::ClientSide); + QCOMPARE(metadata.side, ModPlatform::Side::ClientSide); QCOMPARE(metadata.url, QUrl("https://cdn.modrinth.com/data/kYq5qkSL/versions/1.1.1+1.18/borderless-mining-1.1.1+1.18.jar")); QCOMPARE(metadata.hash_format, "sha512"); @@ -72,7 +73,7 @@ class PackwizTest : public QObject { QCOMPARE(metadata.name, "Screenshot to Clipboard (Fabric)"); QCOMPARE(metadata.filename, "screenshot-to-clipboard-1.0.7-fabric.jar"); - QCOMPARE(metadata.side, Packwiz::V1::Side::UniversalSide); + QCOMPARE(metadata.side, ModPlatform::Side::UniversalSide); QCOMPARE(metadata.url, QUrl("https://edge.forgecdn.net/files/3509/43/screenshot-to-clipboard-1.0.7-fabric.jar")); QCOMPARE(metadata.hash_format, "murmur2"); From 99915018322f37530551175083a041fd35582e28 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 2 Jun 2025 19:28:52 +0300 Subject: [PATCH 002/118] feat: use build config url instead of hadcoded one Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.cpp | 15 ++++++++------- launcher/modplatform/flame/FlameAPI.h | 12 +++++++----- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 15eb7a696..0a5997ed9 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -5,6 +5,7 @@ #include "FlameAPI.h" #include #include +#include "BuildConfig.h" #include "FlameModIndex.h" #include "Application.h" @@ -29,7 +30,7 @@ Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, std::shar QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::ApiUpload::makeByteArray(QString("https://api.curseforge.com/v1/fingerprints"), response, body_raw)); + netJob->addNetAction(Net::ApiUpload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/fingerprints"), response, body_raw)); return netJob; } @@ -42,7 +43,7 @@ QString FlameAPI::getModFileChangelog(int modId, int fileId) auto netJob = makeShared(QString("Flame::FileChangelog"), APPLICATION->network()); auto response = std::make_shared(); netJob->addNetAction(Net::ApiDownload::makeByteArray( - QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog") + QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files/%2/changelog") .arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))), response)); @@ -77,7 +78,7 @@ QString FlameAPI::getModDescription(int modId) auto netJob = makeShared(QString("Flame::ModDescription"), APPLICATION->network()); auto response = std::make_shared(); netJob->addNetAction(Net::ApiDownload::makeByteArray( - QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response)); + QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/description").arg(QString::number(modId)), response)); QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] { QJsonParseError parse_error{}; @@ -117,7 +118,7 @@ Task::Ptr FlameAPI::getProjects(QStringList addonIds, std::shared_ptraddNetAction(Net::ApiUpload::makeByteArray(QString("https://api.curseforge.com/v1/mods"), response, body_raw)); + netJob->addNetAction(Net::ApiUpload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/mods"), response, body_raw)); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); @@ -139,7 +140,7 @@ Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, std::shared_ptraddNetAction(Net::ApiUpload::makeByteArray(QString("https://api.curseforge.com/v1/mods/files"), response, body_raw)); + netJob->addNetAction(Net::ApiUpload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/mods/files"), response, body_raw)); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); @@ -150,7 +151,7 @@ Task::Ptr FlameAPI::getFile(const QString& addonId, const QString& fileId, std:: { auto netJob = makeShared(QString("Flame::GetFile"), APPLICATION->network()); netJob->addNetAction( - Net::ApiDownload::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), response)); + Net::ApiDownload::makeByteArray(QUrl(QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files/%2").arg(addonId, fileId)), response)); QObject::connect(netJob.get(), &NetJob::failed, [addonId, fileId] { qDebug() << "Flame API file failure" << addonId << fileId; }); @@ -174,7 +175,7 @@ Task::Ptr FlameAPI::getCategories(std::shared_ptr response, ModPlatf { auto netJob = makeShared(QString("Flame::GetCategories"), APPLICATION->network()); netJob->addNetAction(Net::ApiDownload::makeByteArray( - QUrl(QString("https://api.curseforge.com/v1/categories?gameId=432&classId=%1").arg(getClassId(type))), response)); + QUrl(QString(BuildConfig.FLAME_BASE_URL + "/categories?gameId=432&classId=%1").arg(getClassId(type))), response)); QObject::connect(netJob.get(), &Task::failed, [](QString msg) { qDebug() << "Flame failed to get categories:" << msg; }); return netJob; } diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 71282f36a..316d2e9c9 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -6,6 +6,7 @@ #include #include +#include "BuildConfig.h" #include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" #include "modplatform/helpers/NetworkResourceAPI.h" @@ -112,18 +113,19 @@ class FlameAPI : public NetworkResourceAPI { if (args.versions.has_value() && !args.versions.value().empty()) get_arguments.append(QString("gameVersion=%1").arg(args.versions.value().front().toString())); - return "https://api.curseforge.com/v1/mods/search?gameId=432&" + get_arguments.join('&'); + return BuildConfig.FLAME_BASE_URL + "/mods/search?gameId=432&" + get_arguments.join('&'); } [[nodiscard]] std::optional getVersionsURL(VersionSearchArgs const& args) const override { auto addonId = args.pack.addonId.toString(); - QString url = QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000").arg(addonId); + QString url = QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files?pageSize=10000").arg(addonId); if (args.mcVersions.has_value()) url += QString("&gameVersion=%1").arg(args.mcVersions.value().front().toString()); - if (args.loaders.has_value() && args.loaders.value() != ModPlatform::ModLoaderType::DataPack && ModPlatform::hasSingleModLoaderSelected(args.loaders.value())) { + if (args.loaders.has_value() && args.loaders.value() != ModPlatform::ModLoaderType::DataPack && + ModPlatform::hasSingleModLoaderSelected(args.loaders.value())) { int mappedModLoader = getMappedModLoader(static_cast(static_cast(args.loaders.value()))); url += QString("&modLoaderType=%1").arg(mappedModLoader); } @@ -133,13 +135,13 @@ class FlameAPI : public NetworkResourceAPI { private: [[nodiscard]] std::optional getInfoURL(QString const& id) const override { - return QString("https://api.curseforge.com/v1/mods/%1").arg(id); + return QString(BuildConfig.FLAME_BASE_URL + "/mods/%1").arg(id); } [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { auto addonId = args.dependency.addonId.toString(); auto url = - QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2").arg(addonId, args.mcVersion.toString()); + QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files?pageSize=10000&gameVersion=%2").arg(addonId, args.mcVersion.toString()); if (args.loader && ModPlatform::hasSingleModLoaderSelected(args.loader)) { int mappedModLoader = getMappedModLoader(static_cast(static_cast(args.loader))); url += QString("&modLoaderType=%1").arg(mappedModLoader); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index bb91e5a64..d4a9a0a48 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -174,7 +174,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde auto response = std::make_shared(); int addonId = current.addonId; netJob->addNetAction( - Net::ApiDownload::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response)); + Net::ApiDownload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files").arg(addonId), response)); QObject::connect(netJob, &NetJob::succeeded, this, [this, response, addonId, curr] { if (addonId != current.addonId) { From f0388d04bf8cbadd9721e6d9be740c277df67cbd Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 6 Jun 2025 22:40:39 +0000 Subject: [PATCH 003/118] Fix MessageLevel.h error when compiling on Debian Stable Signed-off-by: TheKodeToad --- launcher/MessageLevel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/MessageLevel.h b/launcher/MessageLevel.h index 4ffd6bfc2..4c840dfc1 100644 --- a/launcher/MessageLevel.h +++ b/launcher/MessageLevel.h @@ -1,7 +1,7 @@ #pragma once +#include #include -#include /** * @brief the MessageLevel Enum From 8a80ccae3a13b10e5f77f0b3f32347ce8cd9a258 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 7 Jun 2025 09:10:03 +0300 Subject: [PATCH 004/118] chore: move oppacity after checkbox draw Signed-off-by: Trial97 --- launcher/ui/widgets/ProjectItem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp index 91cf0956f..b6701535d 100644 --- a/launcher/ui/widgets/ProjectItem.cpp +++ b/launcher/ui/widgets/ProjectItem.cpp @@ -20,9 +20,6 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o auto isChecked = opt.checkState == Qt::Checked; auto isSelected = option.state & QStyle::State_Selected; - if (!isSelected && !isChecked && isInstalled) { - painter->setOpacity(0.4); // Fade out the entire item - } const QStyle* style = opt.widget == nullptr ? QApplication::style() : opt.widget->style(); auto rect = opt.rect; @@ -39,6 +36,9 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o rect.setX(checkboxOpt.rect.right()); } + if (!isSelected && !isChecked && isInstalled) { + painter->setOpacity(0.4); // Fade out the entire item + } // The default icon size will be a square (and height is usually the lower value). auto icon_width = rect.height(), icon_height = rect.height(); int icon_x_margin = (rect.height() - icon_width) / 2; From 834eb5a90dd943888075274aca12cf5208d21484 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 7 Jun 2025 16:32:40 +0100 Subject: [PATCH 005/118] Don't retry account refresh if aborted Signed-off-by: TheKodeToad --- launcher/LaunchController.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index b1a956b49..824738b6c 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -200,7 +200,7 @@ void LaunchController::login() if ((m_accountToUse->accountType() != AccountType::Offline && m_accountToUse->accountState() == AccountState::Offline) || m_accountToUse->shouldRefresh()) { // Force account refresh on the account used to launch the instance updating the AccountState - // only on first try and if it is not meant to be offline + // only on first try and if it is not meant to be offline m_accountToUse->refresh(); } while (tryagain) { @@ -296,11 +296,21 @@ void LaunchController::login() case AccountState::Working: { // refresh is in progress, we need to wait for it to finish to proceed. ProgressDialog progDialog(m_parentWidget); - if (m_online) { - progDialog.setSkipButton(true, tr("Play Offline")); - } + progDialog.setSkipButton(true, tr("Abort")); + auto task = accountToCheck->currentTask(); + + bool aborted = false; + auto abortListener = connect(task.get(), &Task::aborted, [&aborted] { aborted = true; }); + progDialog.execWithTask(task.get()); + + disconnect(abortListener); + + // don't retry if aborted + if (aborted) + tryagain = false; + continue; } case AccountState::Expired: { From 06aece111ac223c076c0042af86f09428a727050 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 7 Jun 2025 20:24:32 +0100 Subject: [PATCH 006/118] Reset account state on abort Signed-off-by: TheKodeToad --- launcher/minecraft/auth/MinecraftAccount.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index 86e9cc511..ca052c378 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -181,8 +181,10 @@ void MinecraftAccount::authFailed(QString reason) data.validity_ = Validity::None; emit changed(); } break; + case AccountTaskState::STATE_WORKING: { + data.accountState = AccountState::Unchecked; + } break; case AccountTaskState::STATE_CREATED: - case AccountTaskState::STATE_WORKING: case AccountTaskState::STATE_SUCCEEDED: { // Not reachable here, as they are not failures. } From a195b9981d5f42849ed565c58dff673550c42f01 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 7 Jun 2025 22:41:09 +0100 Subject: [PATCH 007/118] Use Task::getState Signed-off-by: TheKodeToad --- launcher/LaunchController.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 824738b6c..26f539e15 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -299,16 +299,10 @@ void LaunchController::login() progDialog.setSkipButton(true, tr("Abort")); auto task = accountToCheck->currentTask(); - - bool aborted = false; - auto abortListener = connect(task.get(), &Task::aborted, [&aborted] { aborted = true; }); - progDialog.execWithTask(task.get()); - disconnect(abortListener); - // don't retry if aborted - if (aborted) + if (task->getState() == Task::State::AbortedByUser) tryagain = false; continue; From ca545b7a5b66f15870936862b7878123c3afd0de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 8 Jun 2025 00:30:27 +0000 Subject: [PATCH 008/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/96ec055edbe5ee227f28cdbc3f1ddf1df5965102?narHash=sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg%3D' (2025-05-28) → 'github:NixOS/nixpkgs/d3d2d80a2191a73d1e86456a751b83aa13085d7d?narHash=sha256-QuUtALJpVrPnPeozlUG/y%2BoIMSLdptHxb3GK6cpSVhA%3D' (2025-06-05) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 2d2f820f4..444e07d05 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1748460289, - "narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=", + "lastModified": 1749143949, + "narHash": "sha256-QuUtALJpVrPnPeozlUG/y+oIMSLdptHxb3GK6cpSVhA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", + "rev": "d3d2d80a2191a73d1e86456a751b83aa13085d7d", "type": "github" }, "original": { From ea1a0daddaae35f448d69fd9c3e008a7b6a5552b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 9 Jun 2025 23:04:20 +0300 Subject: [PATCH 009/118] fix: curseforge optinal blocked mods Signed-off-by: Trial97 --- .../flame/FlameInstanceCreationTask.cpp | 49 +++++++++++-------- .../flame/FlameInstanceCreationTask.h | 2 + launcher/ui/dialogs/BlockedModsDialog.h | 1 + 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index c80187c42..adf4c1065 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -493,16 +493,35 @@ bool FlameCreationTask::createInstance() void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) { - auto results = m_modIdResolver->getResults(); + auto results = m_modIdResolver->getResults().files; + + QStringList optionalFiles; + for (auto& result : results) { + if (!result.required) { + optionalFiles << FS::PathCombine(result.targetFolder, result.version.fileName); + } + } + + if (!optionalFiles.empty()) { + OptionalModDialog optionalModDialog(m_parent, optionalFiles); + if (optionalModDialog.exec() == QDialog::Rejected) { + emitAborted(); + loop.quit(); + return; + } + + m_selectedOptionalMods = optionalModDialog.getResult(); + } // first check for blocked mods QList blocked_mods; auto anyBlocked = false; - for (const auto& result : results.files.values()) { + for (const auto& result : results.values()) { if (result.resourceType != PackedResourceType::Mod) { m_otherResources.append(std::make_pair(result.version.fileName, result.targetFolder)); } + // skip optional mods that were not selected if (result.version.downloadUrl.isEmpty()) { BlockedMod blocked_mod; blocked_mod.name = result.version.fileName; @@ -511,6 +530,10 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) blocked_mod.matched = false; blocked_mod.localPath = ""; blocked_mod.targetFolder = result.targetFolder; + auto fileName = result.version.fileName; + fileName = FS::RemoveInvalidPathChars(fileName); + auto relpath = FS::PathCombine(result.targetFolder, fileName); + blocked_mod.disabled = !result.required && !m_selectedOptionalMods.contains(relpath); blocked_mods.append(blocked_mod); @@ -546,30 +569,12 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) m_filesJob.reset(new NetJob(tr("Mod Download Flame"), APPLICATION->network())); auto results = m_modIdResolver->getResults().files; - QStringList optionalFiles; - for (auto& result : results) { - if (!result.required) { - optionalFiles << FS::PathCombine(result.targetFolder, result.version.fileName); - } - } - - QStringList selectedOptionalMods; - if (!optionalFiles.empty()) { - OptionalModDialog optionalModDialog(m_parent, optionalFiles); - if (optionalModDialog.exec() == QDialog::Rejected) { - emitAborted(); - loop.quit(); - return; - } - - selectedOptionalMods = optionalModDialog.getResult(); - } for (const auto& result : results) { auto fileName = result.version.fileName; fileName = FS::RemoveInvalidPathChars(fileName); auto relpath = FS::PathCombine(result.targetFolder, fileName); - if (!result.required && !selectedOptionalMods.contains(relpath)) { + if (!result.required && !m_selectedOptionalMods.contains(relpath)) { relpath += ".disabled"; } @@ -617,6 +622,8 @@ void FlameCreationTask::copyBlockedMods(QList const& blocked_mods) } auto destPath = FS::PathCombine(m_stagingPath, "minecraft", mod.targetFolder, mod.name); + if (mod.disabled) + destPath += ".disabled"; setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total))); diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h index 3e586a416..e41ce742e 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.h +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h @@ -92,4 +92,6 @@ class FlameCreationTask final : public InstanceCreationTask { QList> m_otherResources; std::optional m_instance; + + QStringList m_selectedOptionalMods; }; diff --git a/launcher/ui/dialogs/BlockedModsDialog.h b/launcher/ui/dialogs/BlockedModsDialog.h index b24e76bbf..15d4d4770 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.h +++ b/launcher/ui/dialogs/BlockedModsDialog.h @@ -42,6 +42,7 @@ struct BlockedMod { bool matched; QString localPath; QString targetFolder; + bool disabled = false; bool move = false; }; From 8df20a372c0a7ee3ce536496af159c18156d5329 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 12 Jun 2025 21:37:39 -0400 Subject: [PATCH 010/118] ci: don't run ci on custom in-tree branches This basically duplicates runs when a PR is opened from an in-tree branch. If we want to run one without a PR, we can use workflow_dispatch anyways Signed-off-by: Seth Flynn --- .github/workflows/build.yml | 5 +++-- .github/workflows/codeql.yml | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f4cdae97c..f744e28ba 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,8 +2,9 @@ name: Build on: push: - branches-ignore: - - "renovate/**" + branches: + - "develop" + - "release-*" paths: # File types - "**.cpp" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f8fae8ecf..8df64878b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -2,6 +2,9 @@ name: "CodeQL Code Scanning" on: push: + branches: + - "develop" + - "release-*" paths: # File types - "**.cpp" From d8ac52bd8c97ea34d6a54613e27431d5f0fe93ee Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 12 Jun 2025 21:39:11 -0400 Subject: [PATCH 011/118] ci: ensure all workflows are actually run on push to branches Oops Signed-off-by: Seth Flynn --- .github/workflows/flatpak.yml | 3 +++ .github/workflows/nix.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/flatpak.yml b/.github/workflows/flatpak.yml index cab0edeb7..26a44d679 100644 --- a/.github/workflows/flatpak.yml +++ b/.github/workflows/flatpak.yml @@ -2,6 +2,9 @@ name: Flatpak on: push: + branches: + - "develop" + - "release-*" # We don't do anything with these artifacts on releases. They go to Flathub tags-ignore: - "*" diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 80b41161a..7b9412c87 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -2,6 +2,9 @@ name: Nix on: push: + branches: + - "develop" + - "release-*" tags: - "*" paths: From 04ecd447bc0df43631face1c20c87f1fd03d3fc0 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 12 Jun 2025 19:58:38 -0400 Subject: [PATCH 012/118] ci(package/linux): use dpkg to determine file paths and variables Should hopefully make things less brittle across different architectures Signed-off-by: Seth Flynn --- .github/actions/package/linux/action.yml | 58 +++++++++++++------ .../setup-dependencies/linux/action.yml | 5 +- .github/workflows/build.yml | 1 + 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/.github/actions/package/linux/action.yml b/.github/actions/package/linux/action.yml index b71e62592..1b4df5de2 100644 --- a/.github/actions/package/linux/action.yml +++ b/.github/actions/package/linux/action.yml @@ -31,6 +31,28 @@ runs: using: composite steps: + - name: Setup build variables + shell: bash + run: | + # Fixup architecture naming for AppImages + dpkg_arch="$(dpkg-architecture -q DEB_HOST_ARCH_CPU)" + case "$dpkg_arch" in + "amd64") + APPIMAGE_ARCH="x86_64" + ;; + "arm64") + APPIMAGE_ARCH="aarch64" + ;; + *) + echo "# 🚨 The Debian architecture \"$deb_arch\" is not recognized!" >> "$GITHUB_STEP_SUMMARY" + exit 1 + ;; + esac + echo "APPIMAGE_ARCH=$APPIMAGE_ARCH" >> "$GITHUB_ENV" + + # Used for the file paths of libraries + echo "DEB_HOST_MULTIARCH=$(dpkg-architecture -q DEB_HOST_MULTIARCH)" >> "$GITHUB_ENV" + - name: Package AppImage shell: bash env: @@ -45,7 +67,7 @@ runs: mv ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/metainfo/org.prismlauncher.PrismLauncher.metainfo.xml ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/metainfo/org.prismlauncher.PrismLauncher.appdata.xml export "NO_APPSTREAM=1" # we have to skip appstream checking because appstream on ubuntu 20.04 is outdated - export OUTPUT="PrismLauncher-Linux-x86_64.AppImage" + export OUTPUT="PrismLauncher-Linux-$APPIMAGE_ARCH.AppImage" chmod +x linuxdeploy-*.AppImage @@ -54,17 +76,17 @@ runs: cp -r ${{ runner.workspace }}/Qt/${{ inputs.qt-version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines - cp /usr/lib/x86_64-linux-gnu/libcrypto.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ - cp /usr/lib/x86_64-linux-gnu/libssl.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ - cp /usr/lib/x86_64-linux-gnu/libOpenGL.so.0* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ + cp /usr/lib/"$DEB_HOST_MULTIARCH"/libcrypto.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ + cp /usr/lib/"$DEB_HOST_MULTIARCH"/libssl.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ + cp /usr/lib/"$DEB_HOST_MULTIARCH"/libOpenGL.so.0* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib" export LD_LIBRARY_PATH - chmod +x AppImageUpdate-x86_64.AppImage - cp AppImageUpdate-x86_64.AppImage ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin + chmod +x AppImageUpdate-"$APPIMAGE_ARCH".AppImage + cp AppImageUpdate-"$APPIMAGE_ARCH".AppImage ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin - export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-x86_64.AppImage.zsync" + export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-$APPIMAGE_ARCH.AppImage.zsync" if [ '${{ inputs.gpg-private-key-id }}' != '' ]; then export SIGN=1 @@ -76,9 +98,9 @@ runs: echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $GITHUB_STEP_SUMMARY fi - ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg + ./linuxdeploy-"$APPIMAGE_ARCH".AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg - mv "PrismLauncher-Linux-x86_64.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build-type }}-x86_64.AppImage" + mv "PrismLauncher-Linux-$APPIMAGE_ARCH.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build-type }}-$APPIMAGE_ARCH.AppImage" - name: Package portable tarball shell: bash @@ -94,11 +116,11 @@ runs: cmake --install ${{ env.BUILD_DIR }} --component portable mkdir ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /lib/x86_64-linux-gnu/libbz2.so.1.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libcrypto.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libssl.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/x86_64-linux-gnu/libffi.so.*.* ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /lib/"$DEB_HOST_MULTIARCH"/libbz2.so.1.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/"$DEB_HOST_MULTIARCH"/libgobject-2.0.so.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/"$DEB_HOST_MULTIARCH"/libcrypto.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/"$DEB_HOST_MULTIARCH"/libssl.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib + cp /usr/lib/"$DEB_HOST_MULTIARCH"/libffi.so.*.* ${{ env.INSTALL_PORTABLE_DIR }}/lib mv ${{ env.INSTALL_PORTABLE_DIR }}/bin/*.so* ${{ env.INSTALL_PORTABLE_DIR }}/lib for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt @@ -114,11 +136,11 @@ runs: - name: Upload AppImage uses: actions/upload-artifact@v4 with: - name: PrismLauncher-${{ inputs.artifact-name }}-${{ inputs.version }}-${{ inputs.build-type }}-x86_64.AppImage - path: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-x86_64.AppImage + name: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-${{ env.APPIMAGE_ARCH }}.AppImage + path: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-${{ env.APPIMAGE_ARCH }}.AppImage - name: Upload AppImage Zsync uses: actions/upload-artifact@v4 with: - name: PrismLauncher-${{ inputs.artifact-name }}-${{ inputs.version }}-${{ inputs.build-type }}-x86_64.AppImage.zsync - path: PrismLauncher-Linux-x86_64.AppImage.zsync + name: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-${{ env.APPIMAGE_ARCH }}.AppImage.zsync + path: PrismLauncher-${{ runner.os }}-${{ env.APPIMAGE_ARCH }}.AppImage.zsync diff --git a/.github/actions/setup-dependencies/linux/action.yml b/.github/actions/setup-dependencies/linux/action.yml index dd0d28364..0569b3d4c 100644 --- a/.github/actions/setup-dependencies/linux/action.yml +++ b/.github/actions/setup-dependencies/linux/action.yml @@ -8,7 +8,10 @@ runs: shell: bash run: | sudo apt-get -y update - sudo apt-get -y install ninja-build extra-cmake-modules scdoc appstream libxcb-cursor-dev + sudo apt-get -y install \ + dpkg-dev \ + ninja-build extra-cmake-modules scdoc \ + appstream libxcb-cursor-dev - name: Setup AppImage tooling shell: bash diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f4cdae97c..602efbeae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -164,6 +164,7 @@ jobs: with: version: ${{ steps.short-version.outputs.version }} build-type: ${{ steps.setup-dependencies.outputs.build-type }} + artifact-name: ${{ matrix.artifact-name }} cmake-preset: ${{ steps.cmake-preset.outputs.preset }} qt-version: ${{ steps.setup-dependencies.outputs.qt-version }} From 6d960b9c3c73385d035bb88744ea33bee1cf2e93 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 12 Jun 2025 20:10:51 -0400 Subject: [PATCH 013/118] ci(setup-deps): always use sccache, simplify restore key sccache is available on arm runners. we can use the restore key for an easy, unique restore key in the cache too (it also prevents us from re-using the ccache caches!) Signed-off-by: Seth Flynn --- .github/actions/setup-dependencies/action.yml | 11 +++++++---- .github/workflows/build.yml | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup-dependencies/action.yml b/.github/actions/setup-dependencies/action.yml index e97abd1df..47a9819ea 100644 --- a/.github/actions/setup-dependencies/action.yml +++ b/.github/actions/setup-dependencies/action.yml @@ -6,6 +6,9 @@ inputs: description: Type for the build required: true default: Debug + artifact-name: + description: Name of the uploaded artifact + required: true msystem: description: MSYS2 subsystem to use required: false @@ -53,16 +56,16 @@ runs: if: ${{ (runner.os != 'Windows' || inputs.msystem == '') && inputs.build-type == 'Debug' }} uses: hendrikmuhs/ccache-action@v1.2.18 with: - variant: ${{ runner.os == 'Windows' && 'sccache' || 'ccache' }} + variant: sccache create-symlink: ${{ runner.os != 'Windows' }} - key: ${{ runner.os }}-qt${{ inputs.qt_ver }}-${{ inputs.architecture }} + key: ${{ runner.os }}-${{ runner.arch }}-${{ inputs.artifact-name }}-sccache - name: Use ccache on debug builds if: ${{ inputs.build-type == 'Debug' }} shell: bash env: - # Only use sccache on MSVC - CCACHE_VARIANT: ${{ (runner.os == 'Windows' && inputs.msystem == '') && 'sccache' || 'ccache' }} + # Only use ccache on MSYS2 + CCACHE_VARIANT: ${{ (runner.os == 'Windows' && inputs.msystem != '') && 'ccache' || 'sccache' }} run: | echo "CMAKE_C_COMPILER_LAUNCHER=$CCACHE_VARIANT" >> "$GITHUB_ENV" echo "CMAKE_CXX_COMPILER_LAUNCHER=$CCACHE_VARIANT" >> "$GITHUB_ENV" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 602efbeae..7df86c3ec 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -126,6 +126,7 @@ jobs: uses: ./.github/actions/setup-dependencies with: build-type: ${{ inputs.build-type || 'Debug' }} + artifact-name: ${{ matrix.artifact-name }} msystem: ${{ matrix.msystem }} vcvars-arch: ${{ matrix.vcvars-arch }} qt-architecture: ${{ matrix.qt-architecture }} From 3718c60844cf080b158108e53d6a4f1c3f7a4428 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 12 Jun 2025 20:42:54 -0400 Subject: [PATCH 014/118] cmake: enforce explicit artifact name It's much easier to determine this in CI and ensure our artifact names are correct (I have made some accidents). They (and thus the updater) can also easily be left out of local builds -- and probably should've always been Signed-off-by: Seth Flynn --- .github/workflows/build.yml | 1 + cmake/commonPresets.json | 1 + cmake/linuxPreset.json | 4 ---- cmake/macosPreset.json | 8 ++------ cmake/windowsMSVCPreset.json | 18 +++--------------- cmake/windowsMinGWPreset.json | 10 ++-------- 6 files changed, 9 insertions(+), 33 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7df86c3ec..c1ee0c761 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -146,6 +146,7 @@ jobs: - name: Run CMake workflow env: CMAKE_PRESET: ${{ steps.cmake-preset.outputs.preset }} + ARTIFACT_NAME: ${{ matrix.artifact-name }}-Qt6 run: | cmake --workflow --preset "$CMAKE_PRESET" diff --git a/cmake/commonPresets.json b/cmake/commonPresets.json index 9cdf51649..2f4cbfa15 100644 --- a/cmake/commonPresets.json +++ b/cmake/commonPresets.json @@ -8,6 +8,7 @@ "binaryDir": "build", "installDir": "install", "cacheVariables": { + "Launcher_BUILD_ARTIFACT": "$penv{ARTIFACT_NAME}", "Launcher_BUILD_PLATFORM": "custom" } }, diff --git a/cmake/linuxPreset.json b/cmake/linuxPreset.json index b8bfe4ff0..984defa5d 100644 --- a/cmake/linuxPreset.json +++ b/cmake/linuxPreset.json @@ -15,7 +15,6 @@ }, "generator": "Ninja", "cacheVariables": { - "Launcher_BUILD_ARTIFACT": "Linux-Qt6", "Launcher_ENABLE_JAVA_DOWNLOADER": "ON" } }, @@ -42,9 +41,6 @@ "linux_base" ], "displayName": "Linux (CI)", - "cacheVariables": { - "Launcher_BUILD_ARTIFACT": "Linux-Qt6" - }, "installDir": "/usr" } ], diff --git a/cmake/macosPreset.json b/cmake/macosPreset.json index 726949934..de503d7a2 100644 --- a/cmake/macosPreset.json +++ b/cmake/macosPreset.json @@ -22,8 +22,7 @@ "macos_base" ], "cacheVariables": { - "CMAKE_OSX_ARCHITECTURES": "x86_64;arm64", - "Launcher_BUILD_ARTIFACT": "macOS-Qt6" + "CMAKE_OSX_ARCHITECTURES": "x86_64;arm64" } }, { @@ -64,10 +63,7 @@ "base_ci", "macos_universal_base" ], - "displayName": "macOS (CI)", - "cacheVariables": { - "Launcher_BUILD_ARTIFACT": "macOS-Qt6" - } + "displayName": "macOS (CI)" } ], "buildPresets": [ diff --git a/cmake/windowsMSVCPreset.json b/cmake/windowsMSVCPreset.json index eb6a38b19..603a0a9ff 100644 --- a/cmake/windowsMSVCPreset.json +++ b/cmake/windowsMSVCPreset.json @@ -12,9 +12,6 @@ "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" - }, - "cacheVariables": { - "Launcher_BUILD_ARTIFACT": "Windows-MSVC-Qt6" } }, { @@ -23,10 +20,7 @@ "inherits": [ "windows_msvc_base" ], - "architecture": "arm64", - "cacheVariables": { - "Launcher_BUILD_ARTIFACT": "Windows-MSVC-arm64-Qt6" - } + "architecture": "arm64" }, { "name": "windows_msvc_debug", @@ -67,10 +61,7 @@ "base_ci", "windows_msvc_base" ], - "displayName": "Windows MSVC (CI)", - "cacheVariables": { - "Launcher_BUILD_ARTIFACT": "Windows-MSVC-Qt6" - } + "displayName": "Windows MSVC (CI)" }, { "name": "windows_msvc_arm64_cross_ci", @@ -78,10 +69,7 @@ "base_ci", "windows_msvc_arm64_cross_base" ], - "displayName": "Windows MSVC (ARM64 cross, CI)", - "cacheVariables": { - "Launcher_BUILD_ARTIFACT": "Windows-MSVC-arm64-Qt6" - } + "displayName": "Windows MSVC (ARM64 cross, CI)" } ], "buildPresets": [ diff --git a/cmake/windowsMinGWPreset.json b/cmake/windowsMinGWPreset.json index 984caadd6..7c4adbcf2 100644 --- a/cmake/windowsMinGWPreset.json +++ b/cmake/windowsMinGWPreset.json @@ -13,10 +13,7 @@ "lhs": "${hostSystemName}", "rhs": "Windows" }, - "generator": "Ninja", - "cacheVariables": { - "Launcher_BUILD_ARTIFACT": "Windows-MinGW-w64-Qt6" - } + "generator": "Ninja" }, { "name": "windows_mingw_debug", @@ -40,10 +37,7 @@ "base_ci", "windows_mingw_base" ], - "displayName": "Windows MinGW (CI)", - "cacheVariables": { - "Launcher_BUILD_ARTIFACT": "Windows-MinGW-w64-Qt6" - } + "displayName": "Windows MinGW (CI)" } ], "buildPresets": [ From c03f854fb8a56bc45179cb54c493eda77019e5ce Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Fri, 13 Jun 2025 02:00:11 -0400 Subject: [PATCH 015/118] cmake: use build platform from environment This allows all CI builds to be deemed "official" Signed-off-by: Seth Flynn --- .github/workflows/build.yml | 2 ++ cmake/commonPresets.json | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c1ee0c761..e656ffcca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -146,7 +146,9 @@ jobs: - name: Run CMake workflow env: CMAKE_PRESET: ${{ steps.cmake-preset.outputs.preset }} + ARTIFACT_NAME: ${{ matrix.artifact-name }}-Qt6 + BUILD_PLATFORM: official run: | cmake --workflow --preset "$CMAKE_PRESET" diff --git a/cmake/commonPresets.json b/cmake/commonPresets.json index 2f4cbfa15..9be0fb447 100644 --- a/cmake/commonPresets.json +++ b/cmake/commonPresets.json @@ -9,7 +9,7 @@ "installDir": "install", "cacheVariables": { "Launcher_BUILD_ARTIFACT": "$penv{ARTIFACT_NAME}", - "Launcher_BUILD_PLATFORM": "custom" + "Launcher_BUILD_PLATFORM": "$penv{BUILD_PLATFORM}" } }, { @@ -40,7 +40,6 @@ "base_release" ], "cacheVariables": { - "Launcher_BUILD_PLATFORM": "official", "Launcher_FORCE_BUNDLED_LIBS": "ON" } } From 03c714cccf61b685cfe349199a1ed06ed3c329ad Mon Sep 17 00:00:00 2001 From: seth Date: Fri, 17 Jan 2025 00:49:32 -0500 Subject: [PATCH 016/118] ci: build for arm on linux Signed-off-by: seth --- .github/actions/package/linux/action.yml | 2 +- .../setup-dependencies/linux/action.yml | 21 ++++++++++++++++--- .github/workflows/build.yml | 8 +++++++ .github/workflows/release.yml | 9 ++++++-- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/.github/actions/package/linux/action.yml b/.github/actions/package/linux/action.yml index 1b4df5de2..d5b0d73f7 100644 --- a/.github/actions/package/linux/action.yml +++ b/.github/actions/package/linux/action.yml @@ -74,7 +74,7 @@ runs: mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines - cp -r ${{ runner.workspace }}/Qt/${{ inputs.qt-version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines + cp -r ${{ runner.workspace }}/Qt/${{ inputs.qt-version }}/gcc_*64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines cp /usr/lib/"$DEB_HOST_MULTIARCH"/libcrypto.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ cp /usr/lib/"$DEB_HOST_MULTIARCH"/libssl.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ diff --git a/.github/actions/setup-dependencies/linux/action.yml b/.github/actions/setup-dependencies/linux/action.yml index 0569b3d4c..94c04abe5 100644 --- a/.github/actions/setup-dependencies/linux/action.yml +++ b/.github/actions/setup-dependencies/linux/action.yml @@ -17,9 +17,24 @@ runs: shell: bash run: | declare -A appimage_deps - appimage_deps["https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20250213-2/linuxdeploy-x86_64.AppImage"]="4648f278ab3ef31f819e67c30d50f462640e5365a77637d7e6f2ad9fd0b4522a linuxdeploy-x86_64.AppImage" - appimage_deps["https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/1-alpha-20250213-1/linuxdeploy-plugin-qt-x86_64.AppImage"]="15106be885c1c48a021198e7e1e9a48ce9d02a86dd0a1848f00bdbf3c1c92724 linuxdeploy-plugin-qt-x86_64.AppImage" - appimage_deps["https://github.com/AppImageCommunity/AppImageUpdate/releases/download/2.0.0-alpha-1-20241225/AppImageUpdate-x86_64.AppImage"]="f1747cf60058e99f1bb9099ee9787d16c10241313b7acec81810ea1b1e568c11 AppImageUpdate-x86_64.AppImage" + + deb_arch="$(dpkg-architecture -q DEB_HOST_ARCH)" + case "$deb_arch" in + "amd64") + appimage_deps["https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20250213-2/linuxdeploy-x86_64.AppImage"]="4648f278ab3ef31f819e67c30d50f462640e5365a77637d7e6f2ad9fd0b4522a linuxdeploy-x86_64.AppImage" + appimage_deps["https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/1-alpha-20250213-1/linuxdeploy-plugin-qt-x86_64.AppImage"]="15106be885c1c48a021198e7e1e9a48ce9d02a86dd0a1848f00bdbf3c1c92724 linuxdeploy-plugin-qt-x86_64.AppImage" + appimage_deps["https://github.com/AppImageCommunity/AppImageUpdate/releases/download/2.0.0-alpha-1-20241225/AppImageUpdate-x86_64.AppImage"]="f1747cf60058e99f1bb9099ee9787d16c10241313b7acec81810ea1b1e568c11 AppImageUpdate-x86_64.AppImage" + ;; + "arm64") + appimage_deps["https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20250213-2/linuxdeploy-aarch64.AppImage"]="06706ac8189797dccd36bd384105892cb5e6e71f784f4df526cc958adc223cd6 linuxdeploy-aarch64.AppImage" + appimage_deps["https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/1-alpha-20250213-1/linuxdeploy-plugin-qt-aarch64.AppImage"]="bf1c24aff6d749b5cf423afad6f15abd4440f81dec1aab95706b25f6667cdcf1 linuxdeploy-plugin-qt-aarch64.AppImage" + appimage_deps["https://github.com/AppImageCommunity/AppImageUpdate/releases/download/2.0.0-alpha-1-20241225/AppImageUpdate-aarch64.AppImage"]="cf27f810dfe5eda41f130769e4a4b562b9d93665371c15ebeffb84ee06a41550 AppImageUpdate-aarch64.AppImage" + ;; + *) + echo "# 🚨 The Debian architecture \"$deb_arch\" is not recognized!" >> "$GITHUB_STEP_SUMMARY" + exit 1 + ;; + esac for url in "${!appimage_deps[@]}"; do curl -LO "$url" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e656ffcca..5eb201fe1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -73,6 +73,14 @@ jobs: artifact-name: Linux base-cmake-preset: linux + # NOTE(@getchoo): Yes, we're intentionally using 24.04 here!!! + # + # It's not really documented anywhere AFAICT, but upstream Qt binaries + # *for the same version* are compiled against 24.04 on ARM, and *not* 22.04 like x64 + - os: ubuntu-24.04-arm + artifact-name: Linux-aarch64 + base-cmake-preset: linux + - os: windows-2022 artifact-name: Windows-MinGW-w64 base-cmake-preset: windows_mingw diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6e879cfd7..264dffbc0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,8 +34,10 @@ jobs: run: | mv ${{ github.workspace }}/PrismLauncher-source PrismLauncher-${{ env.VERSION }} mv PrismLauncher-Linux-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz - mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-x86_64.AppImage - mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync + mv PrismLauncher-*.AppImage/PrismLauncher-*-x86_64.AppImage PrismLauncher-Linux-x86_64.AppImage + mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*-x86_64.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync + mv PrismLauncher-*.AppImage/PrismLauncher-*-aarch64.AppImage PrismLauncher-Linux-aarch64.AppImage + mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*-aarch64.AppImage.zsync PrismLauncher-Linux-aarch64.AppImage.zsync mv PrismLauncher-macOS*/PrismLauncher.zip PrismLauncher-macOS-${{ env.VERSION }}.zip tar --exclude='.git' -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }} @@ -89,7 +91,10 @@ jobs: files: | PrismLauncher-Linux-x86_64.AppImage PrismLauncher-Linux-x86_64.AppImage.zsync + PrismLauncher-Linux-aarch64.AppImage + PrismLauncher-Linux-aarch64.AppImage.zsync PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz + PrismLauncher-Linux-aarch64-Qt6-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip PrismLauncher-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip PrismLauncher-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe From 45027279fa73548dd026903d1953075608ca929d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Jun 2025 00:30:46 +0000 Subject: [PATCH 017/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/d3d2d80a2191a73d1e86456a751b83aa13085d7d?narHash=sha256-QuUtALJpVrPnPeozlUG/y%2BoIMSLdptHxb3GK6cpSVhA%3D' (2025-06-05) → 'github:NixOS/nixpkgs/ee930f9755f58096ac6e8ca94a1887e0534e2d81?narHash=sha256-Kh9K4taXbVuaLC0IL%2B9HcfvxsSUx8dPB5s5weJcc9pc%3D' (2025-06-13) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 444e07d05..18ecd28e2 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1749143949, - "narHash": "sha256-QuUtALJpVrPnPeozlUG/y+oIMSLdptHxb3GK6cpSVhA=", + "lastModified": 1749794982, + "narHash": "sha256-Kh9K4taXbVuaLC0IL+9HcfvxsSUx8dPB5s5weJcc9pc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d3d2d80a2191a73d1e86456a751b83aa13085d7d", + "rev": "ee930f9755f58096ac6e8ca94a1887e0534e2d81", "type": "github" }, "original": { From 4bf6e59f3b1ff22e09c9d085d34db6d70ed1d2cd Mon Sep 17 00:00:00 2001 From: clague <93119153+clague@users.noreply.github.com> Date: Sat, 14 Jun 2025 23:10:49 +0800 Subject: [PATCH 018/118] feat: add ability to change assets download server Signed-off-by: clague <93119153+clague@users.noreply.github.com> --- buildconfig/BuildConfig.h | 2 +- launcher/Application.cpp | 9 ++++++ launcher/minecraft/AssetsUtils.cpp | 7 +++- launcher/minecraft/update/AssetUpdateTask.cpp | 10 +++++- launcher/ui/pages/global/APIPage.cpp | 16 ++++++++++ launcher/ui/pages/global/APIPage.ui | 32 +++++++++++++++++++ 6 files changed, 73 insertions(+), 3 deletions(-) diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 10c38e3d6..045d987d4 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -166,7 +166,7 @@ class Config { QString DISCORD_URL; QString SUBREDDIT_URL; - QString RESOURCE_BASE = "https://resources.download.minecraft.net/"; + QString DEFAULT_RESOURCE_BASE = "https://resources.download.minecraft.net/"; QString LIBRARY_BASE = "https://libraries.minecraft.net/"; QString IMGUR_BASE_URL = "https://api.imgur.com/3/"; QString FMLLIBS_BASE_URL; diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 99b72870b..a4c96d645 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -864,6 +864,15 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // get rid of invalid meta urls if (!metaUrl.isValid() || (metaUrl.scheme() != "http" && metaUrl.scheme() != "https")) m_settings->reset("MetaURLOverride"); + + // Resource URL + m_settings->registerSetting("ResourceURLOverride", ""); + + QUrl resourceUrl(m_settings->get("ResourceURLOverride").toString()); + + // get rid of invalid resource urls + if (!resourceUrl.isValid() || (resourceUrl.scheme() != "http" && resourceUrl.scheme() != "https")) + m_settings->reset("ResourceURLOverride"); } m_settings->registerSetting("CloseAfterLaunch", false); diff --git a/launcher/minecraft/AssetsUtils.cpp b/launcher/minecraft/AssetsUtils.cpp index 083924dc6..d723efc7a 100644 --- a/launcher/minecraft/AssetsUtils.cpp +++ b/launcher/minecraft/AssetsUtils.cpp @@ -298,7 +298,12 @@ QString AssetObject::getLocalPath() QUrl AssetObject::getUrl() { - return BuildConfig.RESOURCE_BASE + getRelPath(); + auto s = APPLICATION->settings(); + auto resourceURL = s->get("ResourceURLOverride").toString(); + if (resourceURL.isEmpty()) { + return BuildConfig.DEFAULT_RESOURCE_BASE + getRelPath(); + } + return resourceURL + getRelPath(); } QString AssetObject::getRelPath() diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp index acdddc833..54cb46e53 100644 --- a/launcher/minecraft/update/AssetUpdateTask.cpp +++ b/launcher/minecraft/update/AssetUpdateTask.cpp @@ -71,7 +71,15 @@ void AssetUpdateTask::assetIndexFinished() auto job = index.getDownloadJob(); if (job) { - setStatus(tr("Getting the assets files from Mojang...")); + QString resourceURLRaw; + auto statusText = tr("Getting the assets files from Mojang..."); + resourceURLRaw = APPLICATION->settings()->get("ResourceURLOverride").toString(); + // FIXME: Need translation + if (!resourceURLRaw.isEmpty()) { + QUrl resourceURL = QUrl(resourceURLRaw); + statusText.replace("Mojang", resourceURL.host()); + } + setStatus(statusText); downloadJob = job; connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::emitSucceeded); connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetsFailed); diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp index a030bf316..83f30f639 100644 --- a/launcher/ui/pages/global/APIPage.cpp +++ b/launcher/ui/pages/global/APIPage.cpp @@ -76,6 +76,7 @@ APIPage::APIPage(QWidget* parent) : QWidget(parent), ui(new Ui::APIPage) updateBaseURLPlaceholder(ui->pasteTypeComboBox->currentIndex()); // NOTE: this allows http://, but we replace that with https later anyway ui->metaURL->setValidator(new QRegularExpressionValidator(s_validUrlRegExp, ui->metaURL)); + ui->resourceURL->setValidator(new QRegularExpressionValidator(s_validUrlRegExp, ui->resourceURL)); ui->baseURLEntry->setValidator(new QRegularExpressionValidator(s_validUrlRegExp, ui->baseURLEntry)); ui->msaClientID->setValidator(new QRegularExpressionValidator(s_validMSAClientID, ui->msaClientID)); ui->flameKey->setValidator(new QRegularExpressionValidator(s_validFlameKey, ui->flameKey)); @@ -137,6 +138,8 @@ void APIPage::loadSettings() ui->msaClientID->setText(msaClientID); QString metaURL = s->get("MetaURLOverride").toString(); ui->metaURL->setText(metaURL); + QString resourceURL = s->get("ResourceURLOverride").toString(); + ui->resourceURL->setText(resourceURL); QString flameKey = s->get("FlameKeyOverride").toString(); ui->flameKey->setText(flameKey); QString modrinthToken = s->get("ModrinthToken").toString(); @@ -156,18 +159,31 @@ void APIPage::applySettings() QString msaClientID = ui->msaClientID->text(); s->set("MSAClientIDOverride", msaClientID); QUrl metaURL(ui->metaURL->text()); + QUrl resourceURL(ui->resourceURL->text()); // Add required trailing slash if (!metaURL.isEmpty() && !metaURL.path().endsWith('/')) { QString path = metaURL.path(); path.append('/'); metaURL.setPath(path); } + + if (!resourceURL.isEmpty() && !resourceURL.path().endsWith('/')) { + QString path = resourceURL.path(); + path.append('/'); + resourceURL.setPath(path); + } // Don't allow HTTP, since meta is basically RCE with all the jar files. if (!metaURL.isEmpty() && metaURL.scheme() == "http") { metaURL.setScheme("https"); } + // Also don't allow HTTP + if (!resourceURL.isEmpty() && resourceURL.scheme() == "http") { + resourceURL.setScheme("https"); + } + s->set("MetaURLOverride", metaURL.toString()); + s->set("ResourceURLOverride", resourceURL.toString()); QString flameKey = ui->flameKey->text(); s->set("FlameKeyOverride", flameKey); QString modrinthToken = ui->modrinthToken->text(); diff --git a/launcher/ui/pages/global/APIPage.ui b/launcher/ui/pages/global/APIPage.ui index c6a4593fc..cc36ff7b2 100644 --- a/launcher/ui/pages/global/APIPage.ui +++ b/launcher/ui/pages/global/APIPage.ui @@ -129,6 +129,38 @@ + + + + Assets Server + + + + + + You can set this to another server if you have problem in downloading assets. + + + Qt::RichText + + + true + + + true + + + + + + + Use Default + + + + + + From 09ec3eb621e11ab0d6668fbecc33a463c001ea37 Mon Sep 17 00:00:00 2001 From: clague <93119153+clague@users.noreply.github.com> Date: Mon, 16 Jun 2025 21:56:23 +0800 Subject: [PATCH 019/118] resolve problems Signed-off-by: clague <93119153+clague@users.noreply.github.com> --- launcher/Application.cpp | 6 +++--- launcher/minecraft/AssetsUtils.cpp | 6 +----- launcher/minecraft/update/AssetUpdateTask.cpp | 14 ++++++-------- launcher/ui/pages/global/APIPage.cpp | 4 ++-- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index a4c96d645..d7182c48d 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -866,13 +866,13 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->reset("MetaURLOverride"); // Resource URL - m_settings->registerSetting("ResourceURLOverride", ""); + m_settings->registerSetting("ResourceURL", BuildConfig.DEFAULT_RESOURCE_BASE); - QUrl resourceUrl(m_settings->get("ResourceURLOverride").toString()); + QUrl resourceUrl(m_settings->get("ResourceURL").toString()); // get rid of invalid resource urls if (!resourceUrl.isValid() || (resourceUrl.scheme() != "http" && resourceUrl.scheme() != "https")) - m_settings->reset("ResourceURLOverride"); + m_settings->reset("ResourceURL"); } m_settings->registerSetting("CloseAfterLaunch", false); diff --git a/launcher/minecraft/AssetsUtils.cpp b/launcher/minecraft/AssetsUtils.cpp index d723efc7a..410d1e689 100644 --- a/launcher/minecraft/AssetsUtils.cpp +++ b/launcher/minecraft/AssetsUtils.cpp @@ -298,11 +298,7 @@ QString AssetObject::getLocalPath() QUrl AssetObject::getUrl() { - auto s = APPLICATION->settings(); - auto resourceURL = s->get("ResourceURLOverride").toString(); - if (resourceURL.isEmpty()) { - return BuildConfig.DEFAULT_RESOURCE_BASE + getRelPath(); - } + auto resourceURL = APPLICATION->settings()->get("ResourceURL").toString(); return resourceURL + getRelPath(); } diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp index 54cb46e53..f4a4022e9 100644 --- a/launcher/minecraft/update/AssetUpdateTask.cpp +++ b/launcher/minecraft/update/AssetUpdateTask.cpp @@ -1,5 +1,6 @@ #include "AssetUpdateTask.h" +#include "BuildConfig.h" #include "launch/LaunchStep.h" #include "minecraft/AssetsUtils.h" #include "minecraft/MinecraftInstance.h" @@ -71,15 +72,12 @@ void AssetUpdateTask::assetIndexFinished() auto job = index.getDownloadJob(); if (job) { - QString resourceURLRaw; - auto statusText = tr("Getting the assets files from Mojang..."); - resourceURLRaw = APPLICATION->settings()->get("ResourceURLOverride").toString(); - // FIXME: Need translation - if (!resourceURLRaw.isEmpty()) { - QUrl resourceURL = QUrl(resourceURLRaw); - statusText.replace("Mojang", resourceURL.host()); + QString resourceURL = APPLICATION->settings()->get("ResourceURL").toString(); + QString source = tr("Mojang"); + if (resourceURL != BuildConfig.DEFAULT_RESOURCE_BASE) { + source = QUrl(resourceURL).host(); } - setStatus(statusText); + setStatus(tr("Getting the assets files from %1...").arg(source)); downloadJob = job; connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::emitSucceeded); connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetsFailed); diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp index 83f30f639..3fedbff72 100644 --- a/launcher/ui/pages/global/APIPage.cpp +++ b/launcher/ui/pages/global/APIPage.cpp @@ -138,7 +138,7 @@ void APIPage::loadSettings() ui->msaClientID->setText(msaClientID); QString metaURL = s->get("MetaURLOverride").toString(); ui->metaURL->setText(metaURL); - QString resourceURL = s->get("ResourceURLOverride").toString(); + QString resourceURL = s->get("ResourceURL").toString(); ui->resourceURL->setText(resourceURL); QString flameKey = s->get("FlameKeyOverride").toString(); ui->flameKey->setText(flameKey); @@ -183,7 +183,7 @@ void APIPage::applySettings() } s->set("MetaURLOverride", metaURL.toString()); - s->set("ResourceURLOverride", resourceURL.toString()); + s->set("ResourceURL", resourceURL.toString()); QString flameKey = ui->flameKey->text(); s->set("FlameKeyOverride", flameKey); QString modrinthToken = ui->modrinthToken->text(); From e9899e3af38d96514bad3eff3e777c9e490bd8f1 Mon Sep 17 00:00:00 2001 From: renner Date: Sun, 15 Jun 2025 13:35:17 +0200 Subject: [PATCH 020/118] chore: refresh metainfo.xml.in adds a donation + FAQ URL and developer id property Signed-off-by: renner --- ...rismlauncher.PrismLauncher.metainfo.xml.in | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/program_info/org.prismlauncher.PrismLauncher.metainfo.xml.in b/program_info/org.prismlauncher.PrismLauncher.metainfo.xml.in index 95bb86a27..747e1bc24 100644 --- a/program_info/org.prismlauncher.PrismLauncher.metainfo.xml.in +++ b/program_info/org.prismlauncher.PrismLauncher.metainfo.xml.in @@ -1,19 +1,13 @@ @Launcher_AppID@ - @Launcher_AppID@.desktop Prism Launcher - Prism Launcher Contributors Custom Minecraft Launcher to easily manage multiple Minecraft installations at once + + Prism Launcher Contributors + CC0-1.0 GPL-3.0-only - https://prismlauncher.org/ - https://prismlauncher.org/wiki/ - https://github.com/PrismLauncher/PrismLauncher/issues - https://prismlauncher.org/discord - https://github.com/PrismLauncher/PrismLauncher - https://github.com/PrismLauncher/PrismLauncher/blob/develop/CONTRIBUTING.md - https://hosted.weblate.org/projects/prismlauncher/launcher

Prism Launcher is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity.

Features:

@@ -67,8 +61,18 @@ + https://prismlauncher.org/ + https://github.com/PrismLauncher/PrismLauncher/issues + https://prismlauncher.org/wiki/overview/faq/ + https://prismlauncher.org/wiki/ + https://opencollective.com/prismlauncher + https://hosted.weblate.org/projects/prismlauncher/launcher + https://prismlauncher.org/discord + https://github.com/PrismLauncher/PrismLauncher + https://github.com/PrismLauncher/PrismLauncher/blob/develop/CONTRIBUTING.md moderate intense + @Launcher_AppID@.desktop
From 21de7a2d97b14064fd2220b45e14a0a353f46f49 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 11 Jun 2025 12:03:59 +0300 Subject: [PATCH 021/118] fix: crash when component version can't be loaded from atlauncher file Signed-off-by: Trial97 --- .../atlauncher/ATLPackInstallTask.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 4f2cca80f..ba3a25aa3 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -434,14 +434,15 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared QList exempt; for (const auto& componentUid : componentsToInstall.keys()) { auto componentVersion = componentsToInstall.value(componentUid); - - for (const auto& library : componentVersion->data()->libraries) { - GradleSpecifier lib(library->rawName()); - exempt.append(lib); + if (componentVersion->data()) { + for (const auto& library : componentVersion->data()->libraries) { + GradleSpecifier lib(library->rawName()); + exempt.append(lib); + } } } - { + if (minecraftVersion->data()) { for (const auto& library : minecraftVersion->data()->libraries) { GradleSpecifier lib(library->rawName()); exempt.append(lib); @@ -582,10 +583,12 @@ bool PackInstallTask::createPackComponent(QString instanceRoot, std::shared_ptr< for (const auto& componentUid : componentsToInstall.keys()) { auto componentVersion = componentsToInstall.value(componentUid); - if (componentVersion->data()->mainClass != QString("")) { - mainClasses.append(componentVersion->data()->mainClass); + if (componentVersion->data()) { + if (componentVersion->data()->mainClass != QString("")) { + mainClasses.append(componentVersion->data()->mainClass); + } + tweakers.append(componentVersion->data()->addTweakers); } - tweakers.append(componentVersion->data()->addTweakers); } auto f = std::make_shared(); From 8711913ac3d65845ab13f668ca682ad901651b0d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 17 Jun 2025 00:43:03 +0100 Subject: [PATCH 022/118] Improve the message when component metadata fails to download Signed-off-by: TheKodeToad --- launcher/minecraft/ComponentUpdateTask.cpp | 5 +++-- launcher/minecraft/ComponentUpdateTask_p.h | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/minecraft/ComponentUpdateTask.cpp b/launcher/minecraft/ComponentUpdateTask.cpp index c77ed248d..56db20205 100644 --- a/launcher/minecraft/ComponentUpdateTask.cpp +++ b/launcher/minecraft/ComponentUpdateTask.cpp @@ -748,7 +748,6 @@ void ComponentUpdateTask::remoteLoadFailed(size_t taskIndex, const QString& msg) d->remoteLoadSuccessful = false; taskSlot.succeeded = false; taskSlot.finished = true; - taskSlot.error = msg; d->remoteTasksInProgress--; checkIfAllFinished(); } @@ -769,7 +768,9 @@ void ComponentUpdateTask::checkIfAllFinished() QStringList allErrorsList; for (auto& item : d->remoteLoadStatusList) { if (!item.succeeded) { - allErrorsList.append(item.error); + const ComponentPtr component = d->m_profile->getComponent(item.PackProfileIndex); + allErrorsList.append(tr("Could not download metadata for %1 %2. Please change the version or try again later.") + .arg(component->getName(), component->m_version)); } } auto allErrors = allErrorsList.join("\n"); diff --git a/launcher/minecraft/ComponentUpdateTask_p.h b/launcher/minecraft/ComponentUpdateTask_p.h index 2fc0b6d9a..8ffb9c71e 100644 --- a/launcher/minecraft/ComponentUpdateTask_p.h +++ b/launcher/minecraft/ComponentUpdateTask_p.h @@ -15,7 +15,6 @@ struct RemoteLoadStatus { size_t PackProfileIndex = 0; bool finished = false; bool succeeded = false; - QString error; Task::Ptr task; }; From 7eb07451cea7facee8698d65e6cb56239fd5e636 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 21 Jun 2025 17:35:51 +0300 Subject: [PATCH 023/118] fix: nightly link Signed-off-by: Trial97 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 361864dfe..868fa1fe1 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Please understand that these builds are not intended for most users. There may b There are development builds available through: - [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions) (includes builds from pull requests opened by contribuitors) -- [nightly.link](https://nightly.link/PrismLauncher/PrismLauncher/workflows/trigger_builds/develop) (this will always point only to the latest version of develop) +- [nightly.link](https://nightly.link/PrismLauncher/PrismLauncher/workflows/build/develop) (this will always point only to the latest version of develop) These have debug information in the binaries, so their file sizes are relatively larger. From f29c5f55819cb9801eda28313a80773c4d0e6df8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Jun 2025 00:30:42 +0000 Subject: [PATCH 024/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/ee930f9755f58096ac6e8ca94a1887e0534e2d81?narHash=sha256-Kh9K4taXbVuaLC0IL%2B9HcfvxsSUx8dPB5s5weJcc9pc%3D' (2025-06-13) → 'github:NixOS/nixpkgs/08f22084e6085d19bcfb4be30d1ca76ecb96fe54?narHash=sha256-XE/lFNhz5lsriMm/yjXkvSZz5DfvKJLUjsS6pP8EC50%3D' (2025-06-19) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 18ecd28e2..9e592824c 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1749794982, - "narHash": "sha256-Kh9K4taXbVuaLC0IL+9HcfvxsSUx8dPB5s5weJcc9pc=", + "lastModified": 1750365781, + "narHash": "sha256-XE/lFNhz5lsriMm/yjXkvSZz5DfvKJLUjsS6pP8EC50=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ee930f9755f58096ac6e8ca94a1887e0534e2d81", + "rev": "08f22084e6085d19bcfb4be30d1ca76ecb96fe54", "type": "github" }, "original": { From ec63f54f48d498eae852242fe285f6556faf868c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 17:38:33 +0000 Subject: [PATCH 025/118] chore(deps): update cachix/install-nix-action digest to f0fe604 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 7480ba46e..3c66a9ef3 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@17fe5fb4a23ad6cbbe47d6b3f359611ad276644c # v31 + - uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31 - uses: DeterminateSystems/update-flake-lock@v25 with: From cdf8ad2c944c1a1196465e0a79a6bc8a43a5a7d1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 25 Jun 2025 13:13:42 +0300 Subject: [PATCH 026/118] fix: escape quetes in shorcut creation arguments Signed-off-by: Trial97 --- launcher/FileSystem.cpp | 48 +++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 5136e7954..308f8620e 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -897,6 +897,29 @@ QString getApplicationsDir() return QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation); } +QString quoteArgs(const QStringList& args, const QString& wrap, const QString& escapeChar, bool wrapOnlyIfNeeded = false) +{ + QString result; + + auto size = args.size(); + for (int i = 0; i < size; ++i) { + QString arg = args[i]; + arg.replace(wrap, escapeChar); + + bool needsWrapping = !wrapOnlyIfNeeded || arg.contains(' ') || arg.contains('\t') || arg.contains(wrap); + + if (needsWrapping) + result += wrap + arg + wrap; + else + result += arg; + + if (i < size - 1) + result += ' '; + } + + return result; +} + // Cross-platform Shortcut creation QString createShortcut(QString destination, QString target, QStringList args, QString name, QString icon) { @@ -940,9 +963,7 @@ QString createShortcut(QString destination, QString target, QStringList args, QS f.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream stream(&f); - QString argstring; - if (!args.empty()) - argstring = " \"" + args.join("\" \"") + "\""; + auto argstring = quoteArgs(args, "\"", "\\\""); stream << "#!/bin/bash" << "\n"; stream << "\"" << target << "\" " << argstring << "\n"; @@ -984,14 +1005,12 @@ QString createShortcut(QString destination, QString target, QStringList args, QS f.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream stream(&f); - QString argstring; - if (!args.empty()) - argstring = " '" + args.join("' '") + "'"; + auto argstring = quoteArgs(args, "'", "'\\''"); stream << "[Desktop Entry]" << "\n"; stream << "Type=Application" << "\n"; stream << "Categories=Game;ActionGame;AdventureGame;Simulation" << "\n"; - stream << "Exec=\"" << target.toLocal8Bit() << "\"" << argstring.toLocal8Bit() << "\n"; + stream << "Exec=\"" << target.toLocal8Bit() << "\" " << argstring.toLocal8Bit() << "\n"; stream << "Name=" << name.toLocal8Bit() << "\n"; if (!icon.isEmpty()) { stream << "Icon=" << icon.toLocal8Bit() << "\n"; @@ -1030,20 +1049,7 @@ QString createShortcut(QString destination, QString target, QStringList args, QS return QString(); } - QString argStr; - int argCount = args.count(); - for (int i = 0; i < argCount; i++) { - if (args[i].contains(' ')) { - argStr.append('"').append(args[i]).append('"'); - } else { - argStr.append(args[i]); - } - - if (i < argCount - 1) { - argStr.append(" "); - } - } - + auto argStr = quoteArgs(args, "\"", "\\\"", true); if (argStr.length() >= MAX_PATH) { qWarning() << "Arguments string is too long!"; return QString(); From bcdbbab7c0ea52404d9b745ca26338aeea2c75f9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 26 Jun 2025 08:37:29 +0000 Subject: [PATCH 027/118] chore(deps): update korthout/backport-action action to v3.2.1 --- .github/workflows/backport.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index c46f8e192..d8f9688d7 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -25,7 +25,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs - uses: korthout/backport-action@v3.2.0 + uses: korthout/backport-action@v3.2.1 with: # Config README: https://github.com/korthout/backport-action#backport-action pull_description: |- From 24d70c773e278f155639b66a1808fe96b221e66d Mon Sep 17 00:00:00 2001 From: Ismail Date: Fri, 27 Jun 2025 00:48:31 +0100 Subject: [PATCH 028/118] fix typo in APIPage.ui Signed-off-by: Ismail --- launcher/ui/pages/global/APIPage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/global/APIPage.ui b/launcher/ui/pages/global/APIPage.ui index c6a4593fc..a822f2b99 100644 --- a/launcher/ui/pages/global/APIPage.ui +++ b/launcher/ui/pages/global/APIPage.ui @@ -170,7 +170,7 @@ - &Microsoft Authentation + &Microsoft Authentication Qt::RichText From 53dcc1576689feebcf12c3004449da66eb84cfac Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 28 Jun 2025 23:34:13 +0300 Subject: [PATCH 029/118] fix: icon import with dot in name Signed-off-by: Trial97 --- launcher/InstanceImportTask.cpp | 10 +++++----- launcher/icons/IconList.cpp | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index c489f6112..77298e2ce 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -263,9 +263,9 @@ void InstanceImportTask::extractFinished() } } -bool installIcon(QString root, QString instIcon) +bool installIcon(QString root, QString instIconKey) { - auto importIconPath = IconUtils::findBestIconIn(root, instIcon); + auto importIconPath = IconUtils::findBestIconIn(root, instIconKey); if (importIconPath.isNull() || !QFile::exists(importIconPath)) importIconPath = IconUtils::findBestIconIn(root, "icon.png"); if (importIconPath.isNull() || !QFile::exists(importIconPath)) @@ -273,10 +273,10 @@ bool installIcon(QString root, QString instIcon) if (!importIconPath.isNull() && QFile::exists(importIconPath)) { // import icon auto iconList = APPLICATION->icons(); - if (iconList->iconFileExists(instIcon)) { - iconList->deleteIcon(instIcon); + if (iconList->iconFileExists(instIconKey)) { + iconList->deleteIcon(instIconKey); } - iconList->installIcon(importIconPath, instIcon); + iconList->installIcon(importIconPath, instIconKey + ".png"); return true; } return false; diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 8a2a482e1..fb80f89da 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -55,7 +55,7 @@ IconList::IconList(const QStringList& builtinPaths, const QString& path, QObject QDir instanceIcons(builtinPath); auto fileInfoList = instanceIcons.entryInfoList(QDir::Files, QDir::Name); for (const auto& fileInfo : fileInfoList) { - builtinNames.insert(fileInfo.baseName()); + builtinNames.insert(fileInfo.completeBaseName()); } } for (const auto& builtinName : builtinNames) { @@ -127,10 +127,11 @@ QStringList IconList::getIconFilePaths() const QString formatName(const QDir& iconsDir, const QFileInfo& iconFile) { if (iconFile.dir() == iconsDir) - return iconFile.baseName(); + return iconFile.completeBaseName(); constexpr auto delimiter = " » "; - QString relativePathWithoutExtension = iconsDir.relativeFilePath(iconFile.dir().path()) + QDir::separator() + iconFile.baseName(); + QString relativePathWithoutExtension = + iconsDir.relativeFilePath(iconFile.dir().path()) + QDir::separator() + iconFile.completeBaseName(); return relativePathWithoutExtension.replace(QDir::separator(), delimiter); } From be62a7d0a25b398debe3f84796e5a288463e9b6c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 29 Jun 2025 00:31:19 +0000 Subject: [PATCH 030/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/08f22084e6085d19bcfb4be30d1ca76ecb96fe54?narHash=sha256-XE/lFNhz5lsriMm/yjXkvSZz5DfvKJLUjsS6pP8EC50%3D' (2025-06-19) → 'github:NixOS/nixpkgs/30e2e2857ba47844aa71991daa6ed1fc678bcbb7?narHash=sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM%3D' (2025-06-27) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 9e592824c..fdcbd87ed 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1750365781, - "narHash": "sha256-XE/lFNhz5lsriMm/yjXkvSZz5DfvKJLUjsS6pP8EC50=", + "lastModified": 1751011381, + "narHash": "sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "08f22084e6085d19bcfb4be30d1ca76ecb96fe54", + "rev": "30e2e2857ba47844aa71991daa6ed1fc678bcbb7", "type": "github" }, "original": { From dac73b394a99bae86dea2f55eb66224bd46fd307 Mon Sep 17 00:00:00 2001 From: seth Date: Mon, 30 Jun 2025 14:54:06 -0400 Subject: [PATCH 031/118] build: emit pdbs on mingw Signed-off-by: seth --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3d60a102..515ea5f1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,15 @@ else() if(WIN32) set(CMAKE_EXE_LINKER_FLAGS "-Wl,--stack,8388608 ${CMAKE_EXE_LINKER_FLAGS}") + # Emit PDBs for WinDbg, etc. + if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + set(CMAKE_EXE_LINKER_FLAGS "-Wl,--pdb= ${CMAKE_EXE_LINKER_FLAGS}") + + foreach(lang C CXX) + set("CMAKE_${lang}_FLAGS" "-gcodeview ${CMAKE_${lang}_FLAGS}") + endforeach() + endif() + # -ffunction-sections and -fdata-sections help reduce binary size # -mguard=cf enables Control Flow Guard # TODO: Look into -gc-sections to further reduce binary size From 71be6eb7d83cefe652f9bf230a2085fd9768e25f Mon Sep 17 00:00:00 2001 From: seth Date: Mon, 30 Jun 2025 14:58:23 -0400 Subject: [PATCH 032/118] build: deploy pdbs with windows builds Signed-off-by: seth --- CMakeLists.txt | 4 ++++ launcher/CMakeLists.txt | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 515ea5f1f..6202f63bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,10 @@ else() foreach(lang C CXX) set("CMAKE_${lang}_FLAGS" "-gcodeview ${CMAKE_${lang}_FLAGS}") + + # Force-enabling this to use generator expressions like TARGET_PDB_FILE + # (and because we can actually emit PDBs) + set("CMAKE_${lang}_LINKER_SUPPORTS_PDB" ON) endforeach() endif() diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 23b2fbfad..5246de19d 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1391,6 +1391,11 @@ install(TARGETS ${Launcher_Name} FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime ) +# Deploy PDBs +if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) + install(FILES $ DESTINATION ${BINARY_DEST_DIR}) +endif() + if(Launcher_BUILD_UPDATER) # Updater add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI}) @@ -1424,6 +1429,11 @@ if(Launcher_BUILD_UPDATER) RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime ) + + # Deploy PDBs + if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) + install(FILES $ DESTINATION ${BINARY_DEST_DIR}) + endif() endif() if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER)) @@ -1464,6 +1474,11 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER)) RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime ) + + # Deploy PDBs + if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) + install(FILES $ DESTINATION ${BINARY_DEST_DIR}) + endif() endif() if (UNIX AND APPLE AND Launcher_ENABLE_UPDATER) From 56fa6586abe6b90dbecf603efafa79b1a9b0647b Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 3 Jul 2025 01:15:29 -0400 Subject: [PATCH 033/118] fix(ui/CustomCommands): memory corruption in labelPostExitCmd Making a QLabel a buddy of itself causes a double free and crashing on deconstruction in some cases (like MSVC) Signed-off-by: Seth Flynn --- launcher/ui/widgets/CustomCommands.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/widgets/CustomCommands.ui b/launcher/ui/widgets/CustomCommands.ui index c1b4558a8..6c1366c06 100644 --- a/launcher/ui/widgets/CustomCommands.ui +++ b/launcher/ui/widgets/CustomCommands.ui @@ -86,7 +86,7 @@ P&ost-exit Command - labelPostExitCmd + postExitCmdTextBox From 364ebbcbe63b13e21f1640deaf05b0c8dcd21eee Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 3 Jul 2025 01:25:49 -0400 Subject: [PATCH 034/118] ci: run on changes to .ui files Signed-off-by: Seth Flynn --- .github/workflows/build.yml | 1 + .github/workflows/codeql.yml | 1 + .github/workflows/flatpak.yml | 1 + .github/workflows/nix.yml | 1 + 4 files changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 98be31627..4954328a9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,6 +10,7 @@ on: - "**.cpp" - "**.h" - "**.java" + - "**.ui" # Directories - "buildconfig/" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 8df64878b..f14bacc02 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -10,6 +10,7 @@ on: - "**.cpp" - "**.h" - "**.java" + - "**.ui" # Directories - "buildconfig/" diff --git a/.github/workflows/flatpak.yml b/.github/workflows/flatpak.yml index 26a44d679..dcfd2ea14 100644 --- a/.github/workflows/flatpak.yml +++ b/.github/workflows/flatpak.yml @@ -13,6 +13,7 @@ on: - "**.cpp" - "**.h" - "**.java" + - "**.ui" # Build files - "flatpak/" diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 7b9412c87..702f8df28 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -12,6 +12,7 @@ on: - "**.cpp" - "**.h" - "**.java" + - "**.ui" # Build files - "**.nix" From 59ed25fad1220c43ed56fa3ed06be42a9a21fb04 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 3 Jul 2025 04:20:52 -0400 Subject: [PATCH 035/118] chore: update to qt 6.9 https://doc.qt.io/qt-6/whatsnew69.html Signed-off-by: Seth Flynn --- .github/actions/setup-dependencies/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-dependencies/action.yml b/.github/actions/setup-dependencies/action.yml index 47a9819ea..e61509c44 100644 --- a/.github/actions/setup-dependencies/action.yml +++ b/.github/actions/setup-dependencies/action.yml @@ -21,7 +21,7 @@ inputs: qt-version: description: Version of Qt to use required: true - default: 6.8.1 + default: 6.9.1 outputs: build-type: From 1deda8cdf4c84a8120d0577778e12200fd085b78 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 3 Jul 2025 04:46:18 -0400 Subject: [PATCH 036/118] build(cmake): set minimum version to 3.22 This requirement was introduced in Qt 6.9 https://doc.qt.io/qt-6/whatsnew69.html#build-system-changes Signed-off-by: Seth Flynn --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6202f63bd..a4d6df243 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15) # minimum version required by QuaZip +cmake_minimum_required(VERSION 3.22) # minimum version required by Qt project(Launcher) From e12c4d0abcb2cc1d135bc3543fb9759ccf28dc92 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 17:40:41 +0000 Subject: [PATCH 037/118] chore(deps): update determinatesystems/nix-installer-action action to v18 --- .github/workflows/nix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 702f8df28..2a9e2db6a 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -108,7 +108,7 @@ jobs: ref: ${{ steps.merge-commit.outputs.merge-commit-sha || github.sha }} - name: Install Nix - uses: DeterminateSystems/nix-installer-action@v17 + uses: DeterminateSystems/nix-installer-action@v18 with: determinate: ${{ env.USE_DETERMINATE }} From 907f661c576d10177672c87409b886215b399887 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 17:40:45 +0000 Subject: [PATCH 038/118] chore(deps): update determinatesystems/update-flake-lock action to v26 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 3c66a9ef3..123028ff2 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31 - - uses: DeterminateSystems/update-flake-lock@v25 + - uses: DeterminateSystems/update-flake-lock@v26 with: commit-msg: "chore(nix): update lockfile" pr-title: "chore(nix): update lockfile" From fde66a11ce102aa2411744c12dec4e7798591af0 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Fri, 4 Jul 2025 05:13:01 -0400 Subject: [PATCH 039/118] build(cmake): apply workaround for ninja in release mode on msvc Signed-off-by: Seth Flynn --- launcher/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 5246de19d..6204acabd 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1458,6 +1458,12 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER)) add_executable("${Launcher_Name}_filelink" WIN32 filelink/filelink_main.cpp) target_sources("${Launcher_Name}_filelink" PRIVATE filelink/filelink.exe.manifest) + # HACK: Fix manifest issues with Ninja in release mode (and only release mode) and MSVC + # I have no idea why this works or why it's needed. UPDATE THIS IF YOU EDIT THE MANIFEST!!! -@getchoo + # Thank you 2018 CMake mailing list thread https://cmake.cmake.narkive.com/LnotZXus/conflicting-msvc-manifests + if(MSVC) + set_property(TARGET "${Launcher_Name}_filelink" PROPERTY LINK_FLAGS "/MANIFESTUAC:level='requireAdministrator'") + endif() target_link_libraries("${Launcher_Name}_filelink" filelink_logic) From 3257abaa34f912d5828f7b5554a91b3d16b1601c Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Fri, 4 Jul 2025 05:16:35 -0400 Subject: [PATCH 040/118] build(cmake): use ninja for msvc release and cross builds Signed-off-by: Seth Flynn --- cmake/windowsMSVCPreset.json | 39 +++++++++--------------------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/cmake/windowsMSVCPreset.json b/cmake/windowsMSVCPreset.json index 603a0a9ff..278f09b94 100644 --- a/cmake/windowsMSVCPreset.json +++ b/cmake/windowsMSVCPreset.json @@ -12,15 +12,15 @@ "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" - } + }, + "generator": "Ninja" }, { "name": "windows_msvc_arm64_cross_base", "hidden": true, "inherits": [ "windows_msvc_base" - ], - "architecture": "arm64" + ] }, { "name": "windows_msvc_debug", @@ -28,8 +28,7 @@ "base_debug", "windows_msvc_base" ], - "displayName": "Windows MSVC (Debug)", - "generator": "Ninja" + "displayName": "Windows MSVC (Debug)" }, { "name": "windows_msvc_release", @@ -98,11 +97,7 @@ ], "displayName": "Windows MSVC (Release)", "configurePreset": "windows_msvc_release", - "configuration": "Release", - "nativeToolOptions": [ - "/p:UseMultiToolTask=true", - "/p:EnforceProcessCountAcrossBuilds=true" - ] + "configuration": "Release" }, { "name": "windows_msvc_arm64_cross_debug", @@ -111,11 +106,7 @@ ], "displayName": "Windows MSVC (ARM64 cross, Debug)", "configurePreset": "windows_msvc_arm64_cross_debug", - "configuration": "Debug", - "nativeToolOptions": [ - "/p:UseMultiToolTask=true", - "/p:EnforceProcessCountAcrossBuilds=true" - ] + "configuration": "Debug" }, { "name": "windows_msvc_arm64_cross_release", @@ -124,11 +115,7 @@ ], "displayName": "Windows MSVC (ARM64 cross, Release)", "configurePreset": "windows_msvc_arm64_cross_release", - "configuration": "Release", - "nativeToolOptions": [ - "/p:UseMultiToolTask=true", - "/p:EnforceProcessCountAcrossBuilds=true" - ] + "configuration": "Release" }, { "name": "windows_msvc_ci", @@ -137,11 +124,7 @@ ], "displayName": "Windows MSVC (CI)", "configurePreset": "windows_msvc_ci", - "configuration": "Release", - "nativeToolOptions": [ - "/p:UseMultiToolTask=true", - "/p:EnforceProcessCountAcrossBuilds=true" - ] + "configuration": "Release" }, { "name": "windows_msvc_arm64_cross_ci", @@ -150,11 +133,7 @@ ], "displayName": "Windows MSVC (ARM64 cross, CI)", "configurePreset": "windows_msvc_arm64_cross_ci", - "configuration": "Release", - "nativeToolOptions": [ - "/p:UseMultiToolTask=true", - "/p:EnforceProcessCountAcrossBuilds=true" - ] + "configuration": "Release" } ], "testPresets": [ From ba6f49b891a85226f57d9a0488b5eee4b4966897 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Fri, 4 Jul 2025 05:27:41 -0400 Subject: [PATCH 041/118] ci: glob directory matches This makes sure *all* changes to directories trigger the given workflows Signed-off-by: Seth Flynn --- .github/workflows/build.yml | 34 ++++++++++++++++++---------------- .github/workflows/codeql.yml | 34 ++++++++++++++++++---------------- .github/workflows/flatpak.yml | 30 ++++++++++++++++-------------- .github/workflows/nix.yml | 30 ++++++++++++++++-------------- 4 files changed, 68 insertions(+), 60 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4954328a9..15de6f70f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,12 +13,12 @@ on: - "**.ui" # Directories - - "buildconfig/" - - "cmake/" - - "launcher/" - - "libraries/" - - "program_info/" - - "tests/" + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "program_info/**" + - "tests/**" # Files - "CMakeLists.txt" @@ -26,21 +26,23 @@ on: # Workflows - ".github/workflows/build.yml" - - ".github/actions/package/" - - ".github/actions/setup-dependencies/" + - ".github/actions/package/**" + - ".github/actions/setup-dependencies/**" pull_request: paths: # File types - "**.cpp" - "**.h" + - "**.java" + - "**.ui" # Directories - - "buildconfig/" - - "cmake/" - - "launcher/" - - "libraries/" - - "program_info/" - - "tests/" + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "program_info/**" + - "tests/**" # Files - "CMakeLists.txt" @@ -48,8 +50,8 @@ on: # Workflows - ".github/workflows/build.yml" - - ".github/actions/package/" - - ".github/actions/setup-dependencies/" + - ".github/actions/package/**" + - ".github/actions/setup-dependencies/**" workflow_call: inputs: build-type: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f14bacc02..964e322b1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -13,43 +13,45 @@ on: - "**.ui" # Directories - - "buildconfig/" - - "cmake/" - - "launcher/" - - "libraries/" - - "program_info/" - - "tests/" + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "program_info/**" + - "tests/**" # Files - "CMakeLists.txt" - "COPYING.md" # Workflows - - ".github/codeql" + - ".github/codeql/**" - ".github/workflows/codeql.yml" - - ".github/actions/setup-dependencies/" + - ".github/actions/setup-dependencies/**" pull_request: paths: # File types - "**.cpp" - "**.h" + - "**.java" + - "**.ui" # Directories - - "buildconfig/" - - "cmake/" - - "launcher/" - - "libraries/" - - "program_info/" - - "tests/" + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "program_info/**" + - "tests/**" # Files - "CMakeLists.txt" - "COPYING.md" # Workflows - - ".github/codeql" + - ".github/codeql/**" - ".github/workflows/codeql.yml" - - ".github/actions/setup-dependencies/" + - ".github/actions/setup-dependencies/**" workflow_dispatch: jobs: diff --git a/.github/workflows/flatpak.yml b/.github/workflows/flatpak.yml index dcfd2ea14..1d5c5e9cc 100644 --- a/.github/workflows/flatpak.yml +++ b/.github/workflows/flatpak.yml @@ -16,15 +16,15 @@ on: - "**.ui" # Build files - - "flatpak/" + - "flatpak/**" # Directories - - "buildconfig/" - - "cmake/" - - "launcher/" - - "libraries/" - - "program_info/" - - "tests/" + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "program_info/**" + - "tests/**" # Files - "CMakeLists.txt" @@ -37,17 +37,19 @@ on: # File types - "**.cpp" - "**.h" + - "**.java" + - "**.ui" # Build files - - "flatpak/" + - "flatpak/**" # Directories - - "buildconfig/" - - "cmake/" - - "launcher/" - - "libraries/" - - "program_info/" - - "tests/" + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "program_info/**" + - "tests/**" # Files - "CMakeLists.txt" diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 2a9e2db6a..ecd71977e 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -16,16 +16,16 @@ on: # Build files - "**.nix" - - "nix/" + - "nix/**" - "flake.lock" # Directories - - "buildconfig/" - - "cmake/" - - "launcher/" - - "libraries/" - - "program_info/" - - "tests/" + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "program_info/**" + - "tests/**" # Files - "CMakeLists.txt" @@ -38,19 +38,21 @@ on: # File types - "**.cpp" - "**.h" + - "**.java" + - "**.ui" # Build files - "**.nix" - - "nix/" + - "nix/**" - "flake.lock" # Directories - - "buildconfig/" - - "cmake/" - - "launcher/" - - "libraries/" - - "program_info/" - - "tests/" + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "program_info/**" + - "tests/**" # Files - "CMakeLists.txt" From 50c8cddb5b4a708f76433c566abdcc3bc8d215d9 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Sat, 5 Jul 2025 02:19:57 -0400 Subject: [PATCH 042/118] build(linux): don't bundle qt with portable zip This was mainly implemented to work around an ABI incompatibility in Arch Linux, which is no longer a major issue as they have an official binary package for us now. Many ABI incompatibility issues still remain (as not every distribution is, or similar to, Ubuntu) which this doesn't even begin to scratch the surface of fixing, and isn't a very supported use case in Linux-land outside of our mostly self-rolled `fixup_bundle` Users who experience ABI incompatibilities with our binaries would be *much* better served using Flatpak or AppImage, as they can guarntee^* compatibility with any host system through a complete bundle; packagers who experience ABI incompatibilities should probably build the launcher against their own distribution, like Arch and many others do Signed-off-by: Seth Flynn --- .github/actions/package/linux/action.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/actions/package/linux/action.yml b/.github/actions/package/linux/action.yml index d5b0d73f7..c5848b089 100644 --- a/.github/actions/package/linux/action.yml +++ b/.github/actions/package/linux/action.yml @@ -111,17 +111,8 @@ runs: INSTALL_PORTABLE_DIR: install-portable run: | - cmake --preset "$CMAKE_PRESET" -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_PORTABLE_DIR }} -DINSTALL_BUNDLE=full - cmake --install ${{ env.BUILD_DIR }} - cmake --install ${{ env.BUILD_DIR }} --component portable - - mkdir ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /lib/"$DEB_HOST_MULTIARCH"/libbz2.so.1.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/"$DEB_HOST_MULTIARCH"/libgobject-2.0.so.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/"$DEB_HOST_MULTIARCH"/libcrypto.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/"$DEB_HOST_MULTIARCH"/libssl.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib - cp /usr/lib/"$DEB_HOST_MULTIARCH"/libffi.so.*.* ${{ env.INSTALL_PORTABLE_DIR }}/lib - mv ${{ env.INSTALL_PORTABLE_DIR }}/bin/*.so* ${{ env.INSTALL_PORTABLE_DIR }}/lib + cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} + cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt cd ${{ env.INSTALL_PORTABLE_DIR }} From fe1a488651ebe5140156a86869ff8c9bcab4d693 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 6 Jul 2025 00:30:52 +0000 Subject: [PATCH 043/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/30e2e2857ba47844aa71991daa6ed1fc678bcbb7?narHash=sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM%3D' (2025-06-27) → 'github:NixOS/nixpkgs/5c724ed1388e53cc231ed98330a60eb2f7be4be3?narHash=sha256-xVNy/XopSfIG9c46nRmPaKfH1Gn/56vQ8%2B%2BxWA8itO4%3D' (2025-07-04) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index fdcbd87ed..17b77e22b 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1751011381, - "narHash": "sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM=", + "lastModified": 1751637120, + "narHash": "sha256-xVNy/XopSfIG9c46nRmPaKfH1Gn/56vQ8++xWA8itO4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30e2e2857ba47844aa71991daa6ed1fc678bcbb7", + "rev": "5c724ed1388e53cc231ed98330a60eb2f7be4be3", "type": "github" }, "original": { From 29d73a474f910934047a213d63ed6f21773b5049 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 7 Jul 2025 20:27:06 +0100 Subject: [PATCH 044/118] Reduce usage of [[nodiscard]] attributes Signed-off-by: TheKodeToad --- launcher/InstanceCopyPrefs.h | 32 ++++----- launcher/InstanceTask.h | 12 ++-- launcher/Version.h | 4 +- launcher/java/JavaInstallList.h | 2 +- launcher/java/download/ArchiveDownloadTask.h | 2 +- launcher/java/download/ManifestDownloadTask.h | 2 +- launcher/meta/Version.h | 2 +- launcher/meta/VersionList.h | 2 +- launcher/minecraft/MinecraftInstance.h | 2 +- launcher/minecraft/World.h | 6 +- launcher/minecraft/auth/MinecraftAccount.h | 2 +- launcher/minecraft/mod/DataPack.h | 8 +-- launcher/minecraft/mod/DataPackFolderModel.h | 6 +- launcher/minecraft/mod/Mod.h | 2 +- launcher/minecraft/mod/Resource.h | 50 ++++++------- .../minecraft/mod/ResourceFolderModel.cpp | 4 +- launcher/minecraft/mod/ResourceFolderModel.h | 40 +++++------ launcher/minecraft/mod/ResourcePack.h | 2 +- .../minecraft/mod/ResourcePackFolderModel.h | 6 +- launcher/minecraft/mod/ShaderPack.h | 2 +- launcher/minecraft/mod/TexturePack.h | 4 +- .../minecraft/mod/TexturePackFolderModel.h | 6 +- launcher/minecraft/mod/WorldSave.h | 4 +- .../mod/tasks/LocalDataPackParseTask.h | 2 +- .../minecraft/mod/tasks/LocalModParseTask.h | 4 +- .../mod/tasks/LocalShaderPackParseTask.h | 4 +- .../mod/tasks/LocalTexturePackParseTask.h | 4 +- .../mod/tasks/LocalWorldSaveParseTask.h | 4 +- .../mod/tasks/ResourceFolderLoadTask.h | 2 +- launcher/modplatform/ModIndex.h | 4 +- launcher/modplatform/ResourceAPI.h | 18 ++--- launcher/modplatform/flame/FlameAPI.h | 10 +-- .../modplatform/helpers/NetworkResourceAPI.h | 8 +-- launcher/modplatform/modrinth/ModrinthAPI.h | 12 ++-- launcher/net/HttpMetaCache.h | 2 +- launcher/tasks/ConcurrentTask.h | 2 +- launcher/ui/dialogs/ResourceDownloadDialog.h | 28 ++++---- launcher/ui/pages/instance/ManagedPackPage.h | 22 +++--- launcher/ui/pages/modplatform/DataPackPage.h | 8 +-- launcher/ui/pages/modplatform/ModPage.h | 8 +-- .../modplatform/ModpackProviderBasePage.h | 2 +- launcher/ui/pages/modplatform/ResourceModel.h | 27 ++++--- .../ui/pages/modplatform/ResourcePackPage.h | 10 +-- launcher/ui/pages/modplatform/ResourcePage.h | 32 ++++----- .../ui/pages/modplatform/ShaderPackPage.h | 10 +-- .../ui/pages/modplatform/TexturePackModel.h | 2 +- .../ui/pages/modplatform/TexturePackPage.h | 4 +- .../ui/pages/modplatform/atlauncher/AtlPage.h | 2 +- .../ui/pages/modplatform/flame/FlameModel.h | 4 +- .../ui/pages/modplatform/flame/FlamePage.h | 2 +- .../modplatform/flame/FlameResourceModels.h | 20 +++--- .../modplatform/flame/FlameResourcePages.h | 70 +++++++++---------- .../modplatform/import_ftb/ImportFTBPage.h | 2 +- .../ui/pages/modplatform/legacy_ftb/Page.h | 2 +- .../modplatform/modrinth/ModrinthModel.h | 4 +- .../pages/modplatform/modrinth/ModrinthPage.h | 2 +- .../modrinth/ModrinthResourceModels.h | 20 +++--- .../modrinth/ModrinthResourcePages.h | 70 +++++++++---------- .../pages/modplatform/technic/TechnicModel.h | 4 +- .../pages/modplatform/technic/TechnicPage.h | 2 +- launcher/ui/widgets/WideBar.cpp | 2 +- launcher/ui/widgets/WideBar.h | 6 +- tests/DummyResourceAPI.h | 4 +- tests/ResourceModel_test.cpp | 2 +- 64 files changed, 323 insertions(+), 326 deletions(-) diff --git a/launcher/InstanceCopyPrefs.h b/launcher/InstanceCopyPrefs.h index 61c51b3b7..1c3c0c984 100644 --- a/launcher/InstanceCopyPrefs.h +++ b/launcher/InstanceCopyPrefs.h @@ -8,23 +8,23 @@ struct InstanceCopyPrefs { public: - [[nodiscard]] bool allTrue() const; - [[nodiscard]] QString getSelectedFiltersAsRegex() const; - [[nodiscard]] QString getSelectedFiltersAsRegex(const QStringList& additionalFilters) const; + bool allTrue() const; + QString getSelectedFiltersAsRegex() const; + QString getSelectedFiltersAsRegex(const QStringList& additionalFilters) const; // Getters - [[nodiscard]] bool isCopySavesEnabled() const; - [[nodiscard]] bool isKeepPlaytimeEnabled() const; - [[nodiscard]] bool isCopyGameOptionsEnabled() const; - [[nodiscard]] bool isCopyResourcePacksEnabled() const; - [[nodiscard]] bool isCopyShaderPacksEnabled() const; - [[nodiscard]] bool isCopyServersEnabled() const; - [[nodiscard]] bool isCopyModsEnabled() const; - [[nodiscard]] bool isCopyScreenshotsEnabled() const; - [[nodiscard]] bool isUseSymLinksEnabled() const; - [[nodiscard]] bool isLinkRecursivelyEnabled() const; - [[nodiscard]] bool isUseHardLinksEnabled() const; - [[nodiscard]] bool isDontLinkSavesEnabled() const; - [[nodiscard]] bool isUseCloneEnabled() const; + bool isCopySavesEnabled() const; + bool isKeepPlaytimeEnabled() const; + bool isCopyGameOptionsEnabled() const; + bool isCopyResourcePacksEnabled() const; + bool isCopyShaderPacksEnabled() const; + bool isCopyServersEnabled() const; + bool isCopyModsEnabled() const; + bool isCopyScreenshotsEnabled() const; + bool isUseSymLinksEnabled() const; + bool isLinkRecursivelyEnabled() const; + bool isUseHardLinksEnabled() const; + bool isDontLinkSavesEnabled() const; + bool isUseCloneEnabled() const; // Setters void enableCopySaves(bool b); void enableKeepPlaytime(bool b); diff --git a/launcher/InstanceTask.h b/launcher/InstanceTask.h index 7c02160a7..86b4cee68 100644 --- a/launcher/InstanceTask.h +++ b/launcher/InstanceTask.h @@ -14,10 +14,10 @@ struct InstanceName { InstanceName() = default; InstanceName(QString name, QString version) : m_original_name(std::move(name)), m_original_version(std::move(version)) {} - [[nodiscard]] QString modifiedName() const; - [[nodiscard]] QString originalName() const; - [[nodiscard]] QString name() const; - [[nodiscard]] QString version() const; + QString modifiedName() const; + QString originalName() const; + QString name() const; + QString version() const; void setName(QString name) { m_modified_name = name; } void setName(InstanceName& other); @@ -44,12 +44,12 @@ class InstanceTask : public Task, public InstanceName { void setGroup(const QString& group) { m_instGroup = group; } QString group() const { return m_instGroup; } - [[nodiscard]] bool shouldConfirmUpdate() const { return m_confirm_update; } + bool shouldConfirmUpdate() const { return m_confirm_update; } void setConfirmUpdate(bool confirm) { m_confirm_update = confirm; } bool shouldOverride() const { return m_override_existing; } - [[nodiscard]] QString originalInstanceID() const { return m_original_instance_id; }; + QString originalInstanceID() const { return m_original_instance_id; }; protected: void setOverride(bool override, QString instance_id_to_override = {}) diff --git a/launcher/Version.h b/launcher/Version.h index 12e7f0832..4b5ea7119 100644 --- a/launcher/Version.h +++ b/launcher/Version.h @@ -96,8 +96,8 @@ class Version { QString m_fullString; - [[nodiscard]] inline bool isAppendix() const { return m_stringPart.startsWith('+'); } - [[nodiscard]] inline bool isPreRelease() const { return m_stringPart.startsWith('-') && m_stringPart.length() > 1; } + inline bool isAppendix() const { return m_stringPart.startsWith('+'); } + inline bool isPreRelease() const { return m_stringPart.startsWith('-') && m_stringPart.length() > 1; } inline bool operator==(const Section& other) const { diff --git a/launcher/java/JavaInstallList.h b/launcher/java/JavaInstallList.h index b77f17b28..c68c2a3be 100644 --- a/launcher/java/JavaInstallList.h +++ b/launcher/java/JavaInstallList.h @@ -35,7 +35,7 @@ class JavaInstallList : public BaseVersionList { public: explicit JavaInstallList(QObject* parent = 0, bool onlyManagedVersions = false); - [[nodiscard]] Task::Ptr getLoadTask() override; + Task::Ptr getLoadTask() override; bool isLoaded() override; const BaseVersion::Ptr at(int i) const override; int count() const override; diff --git a/launcher/java/download/ArchiveDownloadTask.h b/launcher/java/download/ArchiveDownloadTask.h index 1db33763a..4cd919543 100644 --- a/launcher/java/download/ArchiveDownloadTask.h +++ b/launcher/java/download/ArchiveDownloadTask.h @@ -28,7 +28,7 @@ class ArchiveDownloadTask : public Task { ArchiveDownloadTask(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = ""); virtual ~ArchiveDownloadTask() = default; - [[nodiscard]] bool canAbort() const override { return true; } + bool canAbort() const override { return true; } void executeTask() override; virtual bool abort() override; diff --git a/launcher/java/download/ManifestDownloadTask.h b/launcher/java/download/ManifestDownloadTask.h index ae9e0d0ed..0f65b343c 100644 --- a/launcher/java/download/ManifestDownloadTask.h +++ b/launcher/java/download/ManifestDownloadTask.h @@ -29,7 +29,7 @@ class ManifestDownloadTask : public Task { ManifestDownloadTask(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = ""); virtual ~ManifestDownloadTask() = default; - [[nodiscard]] bool canAbort() const override { return true; } + bool canAbort() const override { return true; } void executeTask() override; virtual bool abort() override; diff --git a/launcher/meta/Version.h b/launcher/meta/Version.h index 2327879a1..6bddbf473 100644 --- a/launcher/meta/Version.h +++ b/launcher/meta/Version.h @@ -60,7 +60,7 @@ class Version : public QObject, public BaseVersion, public BaseEntity { QString localFilename() const override; - [[nodiscard]] ::Version toComparableVersion() const; + ::Version toComparableVersion() const; public: // for usage by format parsers only void setType(const QString& type); diff --git a/launcher/meta/VersionList.h b/launcher/meta/VersionList.h index 21c86b751..18681b8ed 100644 --- a/launcher/meta/VersionList.h +++ b/launcher/meta/VersionList.h @@ -37,7 +37,7 @@ class VersionList : public BaseVersionList, public BaseEntity { enum Roles { UidRole = Qt::UserRole + 100, TimeRole, RequiresRole, VersionPtrRole }; bool isLoaded() override; - [[nodiscard]] Task::Ptr getLoadTask() override; + Task::Ptr getLoadTask() override; const BaseVersion::Ptr at(int i) const override; int count() const override; void sortVersions() override; diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index a37164169..c6e519dd2 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -104,7 +104,7 @@ class MinecraftInstance : public BaseInstance { QString getLocalLibraryPath() const; /** Returns whether the instance, with its version, has support for demo mode. */ - [[nodiscard]] bool supportsDemo() const; + bool supportsDemo() const; void updateRuntimeContext() override; diff --git a/launcher/minecraft/World.h b/launcher/minecraft/World.h index 34d418e79..cca931826 100644 --- a/launcher/minecraft/World.h +++ b/launcher/minecraft/World.h @@ -59,7 +59,7 @@ class World { // WEAK compare operator - used for replacing worlds bool operator==(const World& other) const; - [[nodiscard]] auto isSymLink() const -> bool { return m_containerFile.isSymLink(); } + auto isSymLink() const -> bool { return m_containerFile.isSymLink(); } /** * @brief Take a instance path, checks if the file pointed to by the resource is a symlink or under a symlink in that instance @@ -68,9 +68,9 @@ class World { * @return true * @return false */ - [[nodiscard]] bool isSymLinkUnder(const QString& instPath) const; + bool isSymLinkUnder(const QString& instPath) const; - [[nodiscard]] bool isMoreThanOneHardLink() const; + bool isMoreThanOneHardLink() const; QString canonicalFilePath() const { return m_containerFile.canonicalFilePath(); } diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h index f6fcfada2..a82d3f134 100644 --- a/launcher/minecraft/auth/MinecraftAccount.h +++ b/launcher/minecraft/auth/MinecraftAccount.h @@ -114,7 +114,7 @@ class MinecraftAccount : public QObject, public Usable { bool isActive() const; - [[nodiscard]] AccountType accountType() const noexcept { return data.type; } + AccountType accountType() const noexcept { return data.type; } bool ownsMinecraft() const { return data.type != AccountType::Offline && data.minecraftEntitlement.ownsMinecraft; } diff --git a/launcher/minecraft/mod/DataPack.h b/launcher/minecraft/mod/DataPack.h index 4b56cb9d8..ac6408bde 100644 --- a/launcher/minecraft/mod/DataPack.h +++ b/launcher/minecraft/mod/DataPack.h @@ -40,15 +40,15 @@ class DataPack : public Resource { DataPack(QFileInfo file_info) : Resource(file_info) {} /** Gets the numerical ID of the pack format. */ - [[nodiscard]] int packFormat() const { return m_pack_format; } + int packFormat() const { return m_pack_format; } /** Gets, respectively, the lower and upper versions supported by the set pack format. */ - [[nodiscard]] virtual std::pair compatibleVersions() const; + virtual std::pair compatibleVersions() const; /** Gets the description of the data pack. */ - [[nodiscard]] QString description() const { return m_description; } + QString description() const { return m_description; } /** Gets the image of the data pack, converted to a QPixmap for drawing, and scaled to size. */ - [[nodiscard]] QPixmap image(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; + QPixmap image(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; /** Thread-safe. */ void setPackFormat(int new_format_id); diff --git a/launcher/minecraft/mod/DataPackFolderModel.h b/launcher/minecraft/mod/DataPackFolderModel.h index 026ae8b76..2b90e1a2a 100644 --- a/launcher/minecraft/mod/DataPackFolderModel.h +++ b/launcher/minecraft/mod/DataPackFolderModel.h @@ -50,10 +50,10 @@ class DataPackFolderModel : public ResourceFolderModel { virtual QString id() const override { return "datapacks"; } - [[nodiscard]] QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - [[nodiscard]] int columnCount(const QModelIndex& parent) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + int columnCount(const QModelIndex& parent) const override; [[nodiscard]] Resource* createResource(const QFileInfo& file) override; [[nodiscard]] Task* createParseTask(Resource&) override; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 553af92f3..eceb8c256 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -76,7 +76,7 @@ class Mod : public Resource { /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; } /** Gets the icon of the mod, converted to a QPixmap for drawing, and scaled to size. */ - [[nodiscard]] QPixmap icon(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; + QPixmap icon(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; /** Thread-safe. */ QPixmap setIcon(QImage new_image) const; diff --git a/launcher/minecraft/mod/Resource.h b/launcher/minecraft/mod/Resource.h index 16d8c2a89..87bfd4345 100644 --- a/launcher/minecraft/mod/Resource.h +++ b/launcher/minecraft/mod/Resource.h @@ -83,23 +83,23 @@ class Resource : public QObject { void setFile(QFileInfo file_info); void parseFile(); - [[nodiscard]] auto fileinfo() const -> QFileInfo { return m_file_info; } - [[nodiscard]] auto dateTimeChanged() const -> QDateTime { return m_changed_date_time; } - [[nodiscard]] auto internal_id() const -> QString { return m_internal_id; } - [[nodiscard]] auto type() const -> ResourceType { return m_type; } - [[nodiscard]] bool enabled() const { return m_enabled; } - [[nodiscard]] auto getOriginalFileName() const -> QString; - [[nodiscard]] QString sizeStr() const { return m_size_str; } - [[nodiscard]] qint64 sizeInfo() const { return m_size_info; } + auto fileinfo() const -> QFileInfo { return m_file_info; } + auto dateTimeChanged() const -> QDateTime { return m_changed_date_time; } + auto internal_id() const -> QString { return m_internal_id; } + auto type() const -> ResourceType { return m_type; } + bool enabled() const { return m_enabled; } + auto getOriginalFileName() const -> QString; + QString sizeStr() const { return m_size_str; } + qint64 sizeInfo() const { return m_size_info; } - [[nodiscard]] virtual auto name() const -> QString; - [[nodiscard]] virtual bool valid() const { return m_type != ResourceType::UNKNOWN; } + virtual auto name() const -> QString; + virtual bool valid() const { return m_type != ResourceType::UNKNOWN; } - [[nodiscard]] auto status() const -> ResourceStatus { return m_status; }; - [[nodiscard]] auto metadata() -> std::shared_ptr { return m_metadata; } - [[nodiscard]] auto metadata() const -> std::shared_ptr { return m_metadata; } - [[nodiscard]] auto provider() const -> QString; - [[nodiscard]] virtual auto homepage() const -> QString; + auto status() const -> ResourceStatus { return m_status; }; + auto metadata() -> std::shared_ptr { return m_metadata; } + auto metadata() const -> std::shared_ptr { return m_metadata; } + auto provider() const -> QString; + virtual auto homepage() const -> QString; void setStatus(ResourceStatus status) { m_status = status; } void setMetadata(std::shared_ptr&& metadata); @@ -110,12 +110,12 @@ class Resource : public QObject { * = 0: 'this' is equal to 'other' * < 0: 'this' comes before 'other' */ - [[nodiscard]] virtual int compare(Resource const& other, SortType type = SortType::NAME) const; + virtual int compare(Resource const& other, SortType type = SortType::NAME) const; /** Returns whether the given filter should filter out 'this' (false), * or if such filter includes the Resource (true). */ - [[nodiscard]] virtual bool applyFilter(QRegularExpression filter) const; + virtual bool applyFilter(QRegularExpression filter) const; /** Changes the enabled property, according to 'action'. * @@ -123,10 +123,10 @@ class Resource : public QObject { */ bool enable(EnableAction action); - [[nodiscard]] auto shouldResolve() const -> bool { return !m_is_resolving && !m_is_resolved; } - [[nodiscard]] auto isResolving() const -> bool { return m_is_resolving; } - [[nodiscard]] auto isResolved() const -> bool { return m_is_resolved; } - [[nodiscard]] auto resolutionTicket() const -> int { return m_resolution_ticket; } + auto shouldResolve() const -> bool { return !m_is_resolving && !m_is_resolved; } + auto isResolving() const -> bool { return m_is_resolving; } + auto isResolved() const -> bool { return m_is_resolved; } + auto resolutionTicket() const -> int { return m_resolution_ticket; } void setResolving(bool resolving, int resolutionTicket) { @@ -139,7 +139,7 @@ class Resource : public QObject { // Delete the metadata only. auto destroyMetadata(const QDir& index_dir) -> void; - [[nodiscard]] auto isSymLink() const -> bool { return m_file_info.isSymLink(); } + auto isSymLink() const -> bool { return m_file_info.isSymLink(); } /** * @brief Take a instance path, checks if the file pointed to by the resource is a symlink or under a symlink in that instance @@ -148,11 +148,11 @@ class Resource : public QObject { * @return true * @return false */ - [[nodiscard]] bool isSymLinkUnder(const QString& instPath) const; + bool isSymLinkUnder(const QString& instPath) const; - [[nodiscard]] bool isMoreThanOneHardLink() const; + bool isMoreThanOneHardLink() const; - [[nodiscard]] auto mod_id() const -> QString { return m_mod_id; } + auto mod_id() const -> QString { return m_mod_id; } void setModId(const QString& modId) { m_mod_id = modId; } protected: diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index fbcd1b0bc..f93002f06 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -709,7 +709,7 @@ SortType ResourceFolderModel::columnToSortKey(size_t column) const } /* Standard Proxy Model for createFilterProxyModel */ -[[nodiscard]] bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, +bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, [[maybe_unused]] const QModelIndex& source_parent) const { auto* model = qobject_cast(sourceModel()); @@ -721,7 +721,7 @@ SortType ResourceFolderModel::columnToSortKey(size_t column) const return resource.applyFilter(filterRegularExpression()); } -[[nodiscard]] bool ResourceFolderModel::ProxyModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const +bool ResourceFolderModel::ProxyModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const { auto* model = qobject_cast(sourceModel()); if (!model || !source_left.isValid() || !source_right.isValid() || source_left.column() != source_right.column()) { diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 759861e14..0dea3c7f1 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -21,11 +21,11 @@ class QSortFilterProxyModel; /* A macro to define useful functions to handle Resource* -> T* more easily on derived classes */ #define RESOURCE_HELPERS(T) \ - [[nodiscard]] T& at(int index) \ + T& at(int index) \ { \ return *static_cast(m_resources[index].get()); \ } \ - [[nodiscard]] const T& at(int index) const \ + const T& at(int index) const \ { \ return *static_cast(m_resources.at(index).get()); \ } \ @@ -115,24 +115,24 @@ class ResourceFolderModel : public QAbstractListModel { /** Creates a new parse task, if needed, for 'res' and start it.*/ virtual void resolveResource(Resource::Ptr res); - [[nodiscard]] qsizetype size() const { return m_resources.size(); } + qsizetype size() const { return m_resources.size(); } [[nodiscard]] bool empty() const { return size() == 0; } - [[nodiscard]] Resource& at(int index) { return *m_resources[index].get(); } - [[nodiscard]] const Resource& at(int index) const { return *m_resources.at(index).get(); } + Resource& at(int index) { return *m_resources[index].get(); } + const Resource& at(int index) const { return *m_resources.at(index).get(); } QList selectedResources(const QModelIndexList& indexes); QList allResources(); - [[nodiscard]] Resource::Ptr find(QString id); + Resource::Ptr find(QString id); - [[nodiscard]] QDir const& dir() const { return m_dir; } + QDir const& dir() const { return m_dir; } /** Checks whether there's any parse tasks being done. * * Since they can be quite expensive, and are usually done in a separate thread, if we were to destroy the model while having * such tasks would introduce an undefined behavior, most likely resulting in a crash. */ - [[nodiscard]] bool hasPendingParseTasks() const; + bool hasPendingParseTasks() const; /* Qt behavior */ @@ -141,22 +141,22 @@ class ResourceFolderModel : public QAbstractListModel { QStringList columnNames(bool translated = true) const { return translated ? m_column_names_translated : m_column_names; } - [[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast(size()); } - [[nodiscard]] int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; } + int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast(size()); } + int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; } - [[nodiscard]] Qt::DropActions supportedDropActions() const override; + Qt::DropActions supportedDropActions() const override; /// flags, mostly to support drag&drop - [[nodiscard]] Qt::ItemFlags flags(const QModelIndex& index) const override; - [[nodiscard]] QStringList mimeTypes() const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + QStringList mimeTypes() const override; + [[nodiscard]] bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; [[nodiscard]] bool validateIndex(const QModelIndex& index) const; - [[nodiscard]] QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; void setupHeaderAction(QAction* act, int column); void saveColumns(QTreeView* tree); @@ -169,16 +169,16 @@ class ResourceFolderModel : public QAbstractListModel { */ QSortFilterProxyModel* createFilterProxyModel(QObject* parent = nullptr); - [[nodiscard]] SortType columnToSortKey(size_t column) const; - [[nodiscard]] QList columnResizeModes() const { return m_column_resize_modes; } + SortType columnToSortKey(size_t column) const; + QList columnResizeModes() const { return m_column_resize_modes; } class ProxyModel : public QSortFilterProxyModel { public: explicit ProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent) {} protected: - [[nodiscard]] bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; - [[nodiscard]] bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; + bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; }; QString instDirPath() const; diff --git a/launcher/minecraft/mod/ResourcePack.h b/launcher/minecraft/mod/ResourcePack.h index bd161df87..494bdee97 100644 --- a/launcher/minecraft/mod/ResourcePack.h +++ b/launcher/minecraft/mod/ResourcePack.h @@ -22,7 +22,7 @@ class ResourcePack : public DataPack { ResourcePack(QFileInfo file_info) : DataPack(file_info) {} /** Gets, respectively, the lower and upper versions supported by the set pack format. */ - [[nodiscard]] std::pair compatibleVersions() const override; + std::pair compatibleVersions() const override; QString directory() override { return "/assets"; } }; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h index 9dbf41b85..b552c324e 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.h +++ b/launcher/minecraft/mod/ResourcePackFolderModel.h @@ -13,10 +13,10 @@ class ResourcePackFolderModel : public ResourceFolderModel { QString id() const override { return "resourcepacks"; } - [[nodiscard]] QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - [[nodiscard]] int columnCount(const QModelIndex& parent) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + int columnCount(const QModelIndex& parent) const override; [[nodiscard]] Resource* createResource(const QFileInfo& file) override { return new ResourcePack(file); } [[nodiscard]] Task* createParseTask(Resource&) override; diff --git a/launcher/minecraft/mod/ShaderPack.h b/launcher/minecraft/mod/ShaderPack.h index ec0f9404e..9275ebed8 100644 --- a/launcher/minecraft/mod/ShaderPack.h +++ b/launcher/minecraft/mod/ShaderPack.h @@ -45,7 +45,7 @@ class ShaderPack : public Resource { public: using Ptr = shared_qobject_ptr; - [[nodiscard]] ShaderPackFormat packFormat() const { return m_pack_format; } + ShaderPackFormat packFormat() const { return m_pack_format; } ShaderPack(QObject* parent = nullptr) : Resource(parent) {} ShaderPack(QFileInfo file_info) : Resource(file_info) {} diff --git a/launcher/minecraft/mod/TexturePack.h b/launcher/minecraft/mod/TexturePack.h index bf4b5b6b4..1327e2f61 100644 --- a/launcher/minecraft/mod/TexturePack.h +++ b/launcher/minecraft/mod/TexturePack.h @@ -37,10 +37,10 @@ class TexturePack : public Resource { TexturePack(QFileInfo file_info) : Resource(file_info) {} /** Gets the description of the texture pack. */ - [[nodiscard]] QString description() const { return m_description; } + QString description() const { return m_description; } /** Gets the image of the texture pack, converted to a QPixmap for drawing, and scaled to size. */ - [[nodiscard]] QPixmap image(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; + QPixmap image(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; /** Thread-safe. */ void setDescription(QString new_description); diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index 7a9264e8f..37f78d8d7 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -50,10 +50,10 @@ class TexturePackFolderModel : public ResourceFolderModel { virtual QString id() const override { return "texturepacks"; } - [[nodiscard]] QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - [[nodiscard]] int columnCount(const QModelIndex& parent) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + int columnCount(const QModelIndex& parent) const override; [[nodiscard]] Resource* createResource(const QFileInfo& file) override { return new TexturePack(file); } [[nodiscard]] Task* createParseTask(Resource&) override; diff --git a/launcher/minecraft/mod/WorldSave.h b/launcher/minecraft/mod/WorldSave.h index 5985fc8ad..702a3edf6 100644 --- a/launcher/minecraft/mod/WorldSave.h +++ b/launcher/minecraft/mod/WorldSave.h @@ -38,9 +38,9 @@ class WorldSave : public Resource { WorldSave(QFileInfo file_info) : Resource(file_info) {} /** Gets the format of the save. */ - [[nodiscard]] WorldSaveFormat saveFormat() const { return m_save_format; } + WorldSaveFormat saveFormat() const { return m_save_format; } /** Gets the name of the save dir (first found in multi mode). */ - [[nodiscard]] QString saveDirName() const { return m_save_dir_name; } + QString saveDirName() const { return m_save_dir_name; } /** Thread-safe. */ void setSaveFormat(WorldSaveFormat new_save_format); diff --git a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.h b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.h index 57591a0f4..6bdf55880 100644 --- a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.h @@ -61,7 +61,7 @@ class LocalDataPackParseTask : public Task { void executeTask() override; - [[nodiscard]] int token() const { return m_token; } + int token() const { return m_token; } private: int m_token; diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.h b/launcher/minecraft/mod/tasks/LocalModParseTask.h index 7ce5a84d2..cbe009376 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.h @@ -39,13 +39,13 @@ class LocalModParseTask : public Task { using ResultPtr = std::shared_ptr; ResultPtr result() const { return m_result; } - [[nodiscard]] bool canAbort() const override { return true; } + bool canAbort() const override { return true; } bool abort() override; LocalModParseTask(int token, ResourceType type, const QFileInfo& modFile); void executeTask() override; - [[nodiscard]] int token() const { return m_token; } + int token() const { return m_token; } private: int m_token; diff --git a/launcher/minecraft/mod/tasks/LocalShaderPackParseTask.h b/launcher/minecraft/mod/tasks/LocalShaderPackParseTask.h index 6be2183cd..55d77f33b 100644 --- a/launcher/minecraft/mod/tasks/LocalShaderPackParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalShaderPackParseTask.h @@ -46,12 +46,12 @@ class LocalShaderPackParseTask : public Task { public: LocalShaderPackParseTask(int token, ShaderPack& sp); - [[nodiscard]] bool canAbort() const override { return true; } + bool canAbort() const override { return true; } bool abort() override; void executeTask() override; - [[nodiscard]] int token() const { return m_token; } + int token() const { return m_token; } private: int m_token; diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h index 1341590f2..b9cc1ea54 100644 --- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h @@ -50,12 +50,12 @@ class LocalTexturePackParseTask : public Task { public: LocalTexturePackParseTask(int token, TexturePack& rp); - [[nodiscard]] bool canAbort() const override { return true; } + bool canAbort() const override { return true; } bool abort() override; void executeTask() override; - [[nodiscard]] int token() const { return m_token; } + int token() const { return m_token; } private: int m_token; diff --git a/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.h b/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.h index 12f677b02..42faf51c5 100644 --- a/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.h @@ -46,12 +46,12 @@ class LocalWorldSaveParseTask : public Task { public: LocalWorldSaveParseTask(int token, WorldSave& save); - [[nodiscard]] bool canAbort() const override { return true; } + bool canAbort() const override { return true; } bool abort() override; void executeTask() override; - [[nodiscard]] int token() const { return m_token; } + int token() const { return m_token; } private: int m_token; diff --git a/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.h b/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.h index 9950345ef..7c872c13d 100644 --- a/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/ResourceFolderLoadTask.h @@ -60,7 +60,7 @@ class ResourceFolderLoadTask : public Task { bool clean_orphan, std::function create_function); - [[nodiscard]] bool canAbort() const override { return true; } + bool canAbort() const override { return true; } bool abort() override { m_aborted.store(true); diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index ad2503ea7..88a951c34 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -155,14 +155,14 @@ struct IndexedPack { ExtraPackData extraData; // For internal use, not provided by APIs - [[nodiscard]] bool isVersionSelected(int index) const + bool isVersionSelected(int index) const { if (!versionsLoaded) return false; return versions.at(index).is_currently_selected; } - [[nodiscard]] bool isAnyVersionSelected() const + bool isAnyVersionSelected() const { if (!versionsLoaded) return false; diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 62a1ff199..6eed33acf 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -128,7 +128,7 @@ class ResourceAPI { public: /** Gets a list of available sorting methods for this API. */ - [[nodiscard]] virtual auto getSortingMethods() const -> QList = 0; + virtual auto getSortingMethods() const -> QList = 0; public slots: [[nodiscard]] virtual Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&&) const @@ -136,40 +136,40 @@ class ResourceAPI { qWarning() << "TODO: ResourceAPI::searchProjects"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProject([[maybe_unused]] QString addonId, + virtual Task::Ptr getProject([[maybe_unused]] QString addonId, [[maybe_unused]] std::shared_ptr response) const { qWarning() << "TODO: ResourceAPI::getProject"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProjects([[maybe_unused]] QStringList addonIds, + virtual Task::Ptr getProjects([[maybe_unused]] QStringList addonIds, [[maybe_unused]] std::shared_ptr response) const { qWarning() << "TODO: ResourceAPI::getProjects"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const + virtual Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const { qWarning() << "TODO: ResourceAPI::getProjectInfo"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const + virtual Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const { qWarning() << "TODO: ResourceAPI::getProjectVersions"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getDependencyVersion(DependencySearchArgs&&, DependencySearchCallbacks&&) const + virtual Task::Ptr getDependencyVersion(DependencySearchArgs&&, DependencySearchCallbacks&&) const { qWarning() << "TODO"; return nullptr; } protected: - [[nodiscard]] inline QString debugName() const { return "External resource API"; } + inline QString debugName() const { return "External resource API"; } - [[nodiscard]] inline QString mapMCVersionToModrinth(Version v) const + inline QString mapMCVersionToModrinth(Version v) const { static const QString preString = " Pre-Release "; auto verStr = v.toString(); @@ -181,7 +181,7 @@ class ResourceAPI { return verStr; } - [[nodiscard]] inline QString getGameVersionsString(std::list mcVersions) const + inline QString getGameVersionsString(std::list mcVersions) const { QString s; for (auto& ver : mcVersions) { diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 316d2e9c9..8d681aeb5 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -29,7 +29,7 @@ class FlameAPI : public NetworkResourceAPI { static Task::Ptr getModCategories(std::shared_ptr response); static QList loadModCategories(std::shared_ptr response); - [[nodiscard]] QList getSortingMethods() const override; + QList getSortingMethods() const override; static inline bool validateModLoaders(ModPlatform::ModLoaderTypes loaders) { @@ -90,7 +90,7 @@ class FlameAPI : public NetworkResourceAPI { static const QString getModLoaderFilters(ModPlatform::ModLoaderTypes types) { return "[" + getModLoaderStrings(types).join(',') + "]"; } public: - [[nodiscard]] std::optional getSearchURL(SearchArgs const& args) const override + std::optional getSearchURL(SearchArgs const& args) const override { QStringList get_arguments; get_arguments.append(QString("classId=%1").arg(getClassId(args.type))); @@ -116,7 +116,7 @@ class FlameAPI : public NetworkResourceAPI { return BuildConfig.FLAME_BASE_URL + "/mods/search?gameId=432&" + get_arguments.join('&'); } - [[nodiscard]] std::optional getVersionsURL(VersionSearchArgs const& args) const override + std::optional getVersionsURL(VersionSearchArgs const& args) const override { auto addonId = args.pack.addonId.toString(); QString url = QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files?pageSize=10000").arg(addonId); @@ -133,11 +133,11 @@ class FlameAPI : public NetworkResourceAPI { } private: - [[nodiscard]] std::optional getInfoURL(QString const& id) const override + std::optional getInfoURL(QString const& id) const override { return QString(BuildConfig.FLAME_BASE_URL + "/mods/%1").arg(id); } - [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override + std::optional getDependencyURL(DependencySearchArgs const& args) const override { auto addonId = args.dependency.addonId.toString(); auto url = diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.h b/launcher/modplatform/helpers/NetworkResourceAPI.h index b72e82533..d89014a38 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.h +++ b/launcher/modplatform/helpers/NetworkResourceAPI.h @@ -18,8 +18,8 @@ class NetworkResourceAPI : public ResourceAPI { Task::Ptr getDependencyVersion(DependencySearchArgs&&, DependencySearchCallbacks&&) const override; protected: - [[nodiscard]] virtual auto getSearchURL(SearchArgs const& args) const -> std::optional = 0; - [[nodiscard]] virtual auto getInfoURL(QString const& id) const -> std::optional = 0; - [[nodiscard]] virtual auto getVersionsURL(VersionSearchArgs const& args) const -> std::optional = 0; - [[nodiscard]] virtual auto getDependencyURL(DependencySearchArgs const& args) const -> std::optional = 0; + virtual auto getSearchURL(SearchArgs const& args) const -> std::optional = 0; + virtual auto getInfoURL(QString const& id) const -> std::optional = 0; + virtual auto getVersionsURL(VersionSearchArgs const& args) const -> std::optional = 0; + virtual auto getDependencyURL(DependencySearchArgs const& args) const -> std::optional = 0; }; diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 17b23723b..9c48ca4fe 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -35,7 +35,7 @@ class ModrinthAPI : public NetworkResourceAPI { static QList loadModCategories(std::shared_ptr response); public: - [[nodiscard]] auto getSortingMethods() const -> QList override; + auto getSortingMethods() const -> QList override; inline auto getAuthorURL(const QString& name) const -> QString { return "https://modrinth.com/user/" + name; }; @@ -83,7 +83,7 @@ class ModrinthAPI : public NetworkResourceAPI { return {}; } - [[nodiscard]] static inline QString mapMCVersionFromModrinth(QString v) + static inline QString mapMCVersionFromModrinth(QString v) { static const QString preString = " Pre-Release "; bool pre = false; @@ -99,7 +99,7 @@ class ModrinthAPI : public NetworkResourceAPI { } private: - [[nodiscard]] static QString resourceTypeParameter(ModPlatform::ResourceType type) + static QString resourceTypeParameter(ModPlatform::ResourceType type) { switch (type) { case ModPlatform::ResourceType::MOD: @@ -120,7 +120,7 @@ class ModrinthAPI : public NetworkResourceAPI { return ""; } - [[nodiscard]] QString createFacets(SearchArgs const& args) const + QString createFacets(SearchArgs const& args) const { QStringList facets_list; @@ -144,7 +144,7 @@ class ModrinthAPI : public NetworkResourceAPI { } public: - [[nodiscard]] inline auto getSearchURL(SearchArgs const& args) const -> std::optional override + inline auto getSearchURL(SearchArgs const& args) const -> std::optional override { if (args.loaders.has_value() && args.loaders.value() != 0) { if (!validateModLoaders(args.loaders.value())) { @@ -203,7 +203,7 @@ class ModrinthAPI : public NetworkResourceAPI { ModPlatform::DataPack); } - [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override + std::optional getDependencyURL(DependencySearchArgs const& args) const override { return args.dependency.version.length() != 0 ? QString("%1/version/%2").arg(BuildConfig.MODRINTH_PROD_URL, args.dependency.version) : QString("%1/project/%2/version?game_versions=[\"%3\"]&loaders=[\"%4\"]") diff --git a/launcher/net/HttpMetaCache.h b/launcher/net/HttpMetaCache.h index 144012ae5..c8b02dae4 100644 --- a/launcher/net/HttpMetaCache.h +++ b/launcher/net/HttpMetaCache.h @@ -66,7 +66,7 @@ class MetaEntry { /* Whether the entry expires after some time (false) or not (true). */ void makeEternal(bool eternal) { m_is_eternal = eternal; } - [[nodiscard]] bool isEternal() const { return m_is_eternal; } + bool isEternal() const { return m_is_eternal; } auto getCurrentAge() -> qint64 { return m_current_age; } void setCurrentAge(qint64 age) { m_current_age = age; } diff --git a/launcher/tasks/ConcurrentTask.h b/launcher/tasks/ConcurrentTask.h index cc6256cf8..a65613bf2 100644 --- a/launcher/tasks/ConcurrentTask.h +++ b/launcher/tasks/ConcurrentTask.h @@ -88,7 +88,7 @@ class ConcurrentTask : public Task { protected: // NOTE: This is not thread-safe. - [[nodiscard]] unsigned int totalSize() const { return static_cast(m_queue.size() + m_doing.size() + m_done.size()); } + unsigned int totalSize() const { return static_cast(m_queue.size() + m_doing.size() + m_done.size()); } virtual void updateState(); diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 181086d82..a83f3c536 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -57,7 +57,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { void connectButtons(); //: String that gets appended to the download dialog title ("Download " + resourcesString()) - [[nodiscard]] virtual QString resourcesString() const { return tr("resources"); } + virtual QString resourcesString() const { return tr("resources"); } QString dialogTitle() override { return tr("Download %1").arg(resourcesString()); }; @@ -68,7 +68,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { void removeResource(const QString&); const QList getTasks(); - [[nodiscard]] const std::shared_ptr getBaseModel() const { return m_base_model; } + const std::shared_ptr getBaseModel() const { return m_base_model; } void setResourceMetadata(const std::shared_ptr& meta); @@ -82,10 +82,10 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { virtual void confirm(); protected: - [[nodiscard]] virtual QString geometrySaveKey() const { return ""; } + virtual QString geometrySaveKey() const { return ""; } void setButtonStatus(); - [[nodiscard]] virtual GetModDependenciesTask::Ptr getModDependenciesTask() { return nullptr; } + virtual GetModDependenciesTask::Ptr getModDependenciesTask() { return nullptr; } protected: const std::shared_ptr m_base_model; @@ -104,8 +104,8 @@ class ModDownloadDialog final : public ResourceDownloadDialog { ~ModDownloadDialog() override = default; //: String that gets appended to the mod download dialog title ("Download " + resourcesString()) - [[nodiscard]] QString resourcesString() const override { return tr("mods"); } - [[nodiscard]] QString geometrySaveKey() const override { return "ModDownloadGeometry"; } + QString resourcesString() const override { return tr("mods"); } + QString geometrySaveKey() const override { return "ModDownloadGeometry"; } QList getPages() override; GetModDependenciesTask::Ptr getModDependenciesTask() override; @@ -124,8 +124,8 @@ class ResourcePackDownloadDialog final : public ResourceDownloadDialog { ~ResourcePackDownloadDialog() override = default; //: String that gets appended to the resource pack download dialog title ("Download " + resourcesString()) - [[nodiscard]] QString resourcesString() const override { return tr("resource packs"); } - [[nodiscard]] QString geometrySaveKey() const override { return "RPDownloadGeometry"; } + QString resourcesString() const override { return tr("resource packs"); } + QString geometrySaveKey() const override { return "RPDownloadGeometry"; } QList getPages() override; @@ -143,8 +143,8 @@ class TexturePackDownloadDialog final : public ResourceDownloadDialog { ~TexturePackDownloadDialog() override = default; //: String that gets appended to the texture pack download dialog title ("Download " + resourcesString()) - [[nodiscard]] QString resourcesString() const override { return tr("texture packs"); } - [[nodiscard]] QString geometrySaveKey() const override { return "TPDownloadGeometry"; } + QString resourcesString() const override { return tr("texture packs"); } + QString geometrySaveKey() const override { return "TPDownloadGeometry"; } QList getPages() override; @@ -160,8 +160,8 @@ class ShaderPackDownloadDialog final : public ResourceDownloadDialog { ~ShaderPackDownloadDialog() override = default; //: String that gets appended to the shader pack download dialog title ("Download " + resourcesString()) - [[nodiscard]] QString resourcesString() const override { return tr("shader packs"); } - [[nodiscard]] QString geometrySaveKey() const override { return "ShaderDownloadGeometry"; } + QString resourcesString() const override { return tr("shader packs"); } + QString geometrySaveKey() const override { return "ShaderDownloadGeometry"; } QList getPages() override; @@ -177,8 +177,8 @@ class DataPackDownloadDialog final : public ResourceDownloadDialog { ~DataPackDownloadDialog() override = default; //: String that gets appended to the data pack download dialog title ("Download " + resourcesString()) - [[nodiscard]] QString resourcesString() const override { return tr("data packs"); } - [[nodiscard]] QString geometrySaveKey() const override { return "DataPackDownloadGeometry"; } + QString resourcesString() const override { return tr("data packs"); } + QString geometrySaveKey() const override { return "DataPackDownloadGeometry"; } QList getPages() override; diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index e8d304c6b..966c57768 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -37,11 +37,11 @@ class ManagedPackPage : public QWidget, public BasePage { static ManagedPackPage* createPage(BaseInstance* inst, QString type, QWidget* parent = nullptr); ~ManagedPackPage() override; - [[nodiscard]] QString displayName() const override; - [[nodiscard]] QIcon icon() const override; - [[nodiscard]] QString helpPage() const override; - [[nodiscard]] QString id() const override { return "managed_pack"; } - [[nodiscard]] bool shouldDisplay() const override; + QString displayName() const override; + QIcon icon() const override; + QString helpPage() const override; + QString id() const override { return "managed_pack"; } + bool shouldDisplay() const override; void openedImpl() override; @@ -55,7 +55,7 @@ class ManagedPackPage : public QWidget, public BasePage { /** URL of the managed pack. * Not the version-specific one. */ - [[nodiscard]] virtual QString url() const { return {}; }; + virtual QString url() const { return {}; }; void setInstanceWindow(InstanceWindow* window) { m_instance_window = window; } @@ -109,7 +109,7 @@ class GenericManagedPackPage final : public ManagedPackPage { ~GenericManagedPackPage() override = default; // TODO: We may want to show this page with some useful info at some point. - [[nodiscard]] bool shouldDisplay() const override { return false; }; + bool shouldDisplay() const override { return false; }; }; class ModrinthManagedPackPage final : public ManagedPackPage { @@ -120,8 +120,8 @@ class ModrinthManagedPackPage final : public ManagedPackPage { ~ModrinthManagedPackPage() override = default; void parseManagedPack() override; - [[nodiscard]] QString url() const override; - [[nodiscard]] QString helpPage() const override { return "modrinth-managed-pack"; } + QString url() const override; + QString helpPage() const override { return "modrinth-managed-pack"; } public slots: void suggestVersion() override; @@ -144,8 +144,8 @@ class FlameManagedPackPage final : public ManagedPackPage { ~FlameManagedPackPage() override = default; void parseManagedPack() override; - [[nodiscard]] QString url() const override; - [[nodiscard]] QString helpPage() const override { return "curseforge-managed-pack"; } + QString url() const override; + QString helpPage() const override { return "curseforge-managed-pack"; } public slots: void suggestVersion() override; diff --git a/launcher/ui/pages/modplatform/DataPackPage.h b/launcher/ui/pages/modplatform/DataPackPage.h index cf78df96c..431fc9a05 100644 --- a/launcher/ui/pages/modplatform/DataPackPage.h +++ b/launcher/ui/pages/modplatform/DataPackPage.h @@ -34,13 +34,13 @@ class DataPackResourcePage : public ResourcePage { } //: The plural version of 'data pack' - [[nodiscard]] inline QString resourcesString() const override { return tr("data packs"); } + inline QString resourcesString() const override { return tr("data packs"); } //: The singular version of 'data packs' - [[nodiscard]] inline QString resourceString() const override { return tr("data pack"); } + inline QString resourceString() const override { return tr("data pack"); } - [[nodiscard]] bool supportsFiltering() const override { return false; }; + bool supportsFiltering() const override { return false; }; - [[nodiscard]] QMap urlHandlers() const override; + QMap urlHandlers() const override; protected: DataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance); diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index fb9f3f9d3..d3b08cbd9 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -43,17 +43,17 @@ class ModPage : public ResourcePage { } //: The plural version of 'mod' - [[nodiscard]] inline QString resourcesString() const override { return tr("mods"); } + inline QString resourcesString() const override { return tr("mods"); } //: The singular version of 'mods' - [[nodiscard]] inline QString resourceString() const override { return tr("mod"); } + inline QString resourceString() const override { return tr("mod"); } - [[nodiscard]] QMap urlHandlers() const override; + QMap urlHandlers() const override; void addResourceToPage(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, std::shared_ptr) override; virtual std::unique_ptr createFilterWidget() = 0; - [[nodiscard]] bool supportsFiltering() const override { return true; }; + bool supportsFiltering() const override { return true; }; auto getFilter() const -> const std::shared_ptr { return m_filter; } void setFilterWidget(std::unique_ptr&); diff --git a/launcher/ui/pages/modplatform/ModpackProviderBasePage.h b/launcher/ui/pages/modplatform/ModpackProviderBasePage.h index a3daa9a81..6cc0b8e99 100644 --- a/launcher/ui/pages/modplatform/ModpackProviderBasePage.h +++ b/launcher/ui/pages/modplatform/ModpackProviderBasePage.h @@ -25,5 +25,5 @@ class ModpackProviderBasePage : public BasePage { /** Programatically set the term in the search bar. */ virtual void setSearchTerm(QString) = 0; /** Get the current term in the search bar. */ - [[nodiscard]] virtual QString getSerachTerm() const = 0; + virtual QString getSerachTerm() const = 0; }; \ No newline at end of file diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 3f1e633ec..cae1d6581 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -36,25 +36,25 @@ class ResourceModel : public QAbstractListModel { ResourceModel(ResourceAPI* api); ~ResourceModel() override; - [[nodiscard]] auto data(const QModelIndex&, int role) const -> QVariant override; - [[nodiscard]] auto roleNames() const -> QHash override; + auto data(const QModelIndex&, int role) const -> QVariant override; + auto roleNames() const -> QHash override; bool setData(const QModelIndex& index, const QVariant& value, int role) override; - [[nodiscard]] virtual auto debugName() const -> QString; - [[nodiscard]] virtual auto metaEntryBase() const -> QString = 0; + virtual auto debugName() const -> QString; + virtual auto metaEntryBase() const -> QString = 0; - [[nodiscard]] inline int rowCount(const QModelIndex& parent) const override + inline int rowCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : static_cast(m_packs.size()); } - [[nodiscard]] inline int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : 1; } - [[nodiscard]] inline auto flags(const QModelIndex& index) const -> Qt::ItemFlags override { return QAbstractListModel::flags(index); } + inline int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : 1; } + inline auto flags(const QModelIndex& index) const -> Qt::ItemFlags override { return QAbstractListModel::flags(index); } - [[nodiscard]] bool hasActiveSearchJob() const { return m_current_search_job && m_current_search_job->isRunning(); } - [[nodiscard]] bool hasActiveInfoJob() const { return m_current_info_job.isRunning(); } - [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? m_current_search_job : nullptr; } + bool hasActiveSearchJob() const { return m_current_search_job && m_current_search_job->isRunning(); } + bool hasActiveInfoJob() const { return m_current_info_job.isRunning(); } + Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? m_current_search_job : nullptr; } - [[nodiscard]] auto getSortingMethods() const { return m_api->getSortingMethods(); } + auto getSortingMethods() const { return m_api->getSortingMethods(); } virtual QVariant getInstalledPackVersion(ModPlatform::IndexedPack::Ptr) const { return {}; } /** Whether the version is opted out or not. Currently only makes sense in CF. */ @@ -69,7 +69,6 @@ class ResourceModel : public QAbstractListModel { public slots: void fetchMore(const QModelIndex& parent) override; - // NOTE: Can't use [[nodiscard]] here because of https://bugreports.qt.io/browse/QTBUG-58628 on Qt 5.12 inline bool canFetchMore(const QModelIndex& parent) const override { return parent.isValid() ? false : m_search_state == SearchState::CanFetchMore; @@ -113,14 +112,14 @@ class ResourceModel : public QAbstractListModel { void runSearchJob(Task::Ptr); void runInfoJob(Task::Ptr); - [[nodiscard]] auto getCurrentSortingMethodByIndex() const -> std::optional; + auto getCurrentSortingMethodByIndex() const -> std::optional; /** Converts a JSON document to a common array format. * * This is needed so that different providers, with different JSON structures, can be parsed * uniformally. You NEED to re-implement this if you intend on using the default callbacks. */ - [[nodiscard]] virtual auto documentToArray(QJsonDocument&) const -> QJsonArray; + virtual auto documentToArray(QJsonDocument&) const -> QJsonArray; /** Functions to load data into a pack. * diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.h b/launcher/ui/pages/modplatform/ResourcePackPage.h index 8d967f73a..f8d4d5bf9 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.h +++ b/launcher/ui/pages/modplatform/ResourcePackPage.h @@ -33,15 +33,15 @@ class ResourcePackResourcePage : public ResourcePage { } //: The plural version of 'resource pack' - [[nodiscard]] inline QString resourcesString() const override { return tr("resource packs"); } + inline QString resourcesString() const override { return tr("resource packs"); } //: The singular version of 'resource packs' - [[nodiscard]] inline QString resourceString() const override { return tr("resource pack"); } + inline QString resourceString() const override { return tr("resource pack"); } - [[nodiscard]] bool supportsFiltering() const override { return false; }; + bool supportsFiltering() const override { return false; }; - [[nodiscard]] QMap urlHandlers() const override; + QMap urlHandlers() const override; - [[nodiscard]] inline auto helpPage() const -> QString override { return "resourcepack-platform"; } + inline auto helpPage() const -> QString override { return "resourcepack-platform"; } protected: ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance); diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index 055db441a..8f4d2c496 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -33,37 +33,37 @@ class ResourcePage : public QWidget, public BasePage { ~ResourcePage() override; /* Affects what the user sees */ - [[nodiscard]] auto displayName() const -> QString override = 0; - [[nodiscard]] auto icon() const -> QIcon override = 0; - [[nodiscard]] auto id() const -> QString override = 0; - [[nodiscard]] auto helpPage() const -> QString override = 0; - [[nodiscard]] bool shouldDisplay() const override = 0; + auto displayName() const -> QString override = 0; + auto icon() const -> QIcon override = 0; + auto id() const -> QString override = 0; + auto helpPage() const -> QString override = 0; + bool shouldDisplay() const override = 0; /* Used internally */ - [[nodiscard]] virtual auto metaEntryBase() const -> QString = 0; - [[nodiscard]] virtual auto debugName() const -> QString = 0; + virtual auto metaEntryBase() const -> QString = 0; + virtual auto debugName() const -> QString = 0; //: The plural version of 'resource' - [[nodiscard]] virtual inline QString resourcesString() const { return tr("resources"); } + virtual inline QString resourcesString() const { return tr("resources"); } //: The singular version of 'resources' - [[nodiscard]] virtual inline QString resourceString() const { return tr("resource"); } + virtual inline QString resourceString() const { return tr("resource"); } /* Features this resource's page supports */ - [[nodiscard]] virtual bool supportsFiltering() const = 0; + virtual bool supportsFiltering() const = 0; void retranslate() override; void openedImpl() override; auto eventFilter(QObject* watched, QEvent* event) -> bool override; /** Get the current term in the search bar. */ - [[nodiscard]] auto getSearchTerm() const -> QString; + auto getSearchTerm() const -> QString; /** Programatically set the term in the search bar. */ void setSearchTerm(QString); - [[nodiscard]] bool setCurrentPack(ModPlatform::IndexedPack::Ptr); - [[nodiscard]] auto getCurrentPack() const -> ModPlatform::IndexedPack::Ptr; - [[nodiscard]] auto getDialog() const -> const ResourceDownloadDialog* { return m_parentDialog; } - [[nodiscard]] auto getModel() const -> ResourceModel* { return m_model; } + bool setCurrentPack(ModPlatform::IndexedPack::Ptr); + auto getCurrentPack() const -> ModPlatform::IndexedPack::Ptr; + auto getDialog() const -> const ResourceDownloadDialog* { return m_parentDialog; } + auto getModel() const -> ResourceModel* { return m_model; } protected: ResourcePage(ResourceDownloadDialog* parent, BaseInstance&); @@ -95,8 +95,6 @@ class ResourcePage : public QWidget, public BasePage { void onResourceSelected(); void onResourceToggle(const QModelIndex& index); - // NOTE: Can't use [[nodiscard]] here because of https://bugreports.qt.io/browse/QTBUG-58628 on Qt 5.12 - /** Associates regex expressions to pages in the order they're given in the map. */ virtual QMap urlHandlers() const = 0; virtual void openUrl(const QUrl&); diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h index d436e218a..85d2b16e6 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.h +++ b/launcher/ui/pages/modplatform/ShaderPackPage.h @@ -33,17 +33,17 @@ class ShaderPackResourcePage : public ResourcePage { } //: The plural version of 'shader pack' - [[nodiscard]] inline QString resourcesString() const override { return tr("shader packs"); } + inline QString resourcesString() const override { return tr("shader packs"); } //: The singular version of 'shader packs' - [[nodiscard]] inline QString resourceString() const override { return tr("shader pack"); } + inline QString resourceString() const override { return tr("shader pack"); } - [[nodiscard]] bool supportsFiltering() const override { return false; }; + bool supportsFiltering() const override { return false; }; void addResourceToPage(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, std::shared_ptr) override; - [[nodiscard]] QMap urlHandlers() const override; + QMap urlHandlers() const override; - [[nodiscard]] inline auto helpPage() const -> QString override { return "shaderpack-platform"; } + inline auto helpPage() const -> QString override { return "shaderpack-platform"; } protected: ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); diff --git a/launcher/ui/pages/modplatform/TexturePackModel.h b/launcher/ui/pages/modplatform/TexturePackModel.h index 45b5734ee..885bbced8 100644 --- a/launcher/ui/pages/modplatform/TexturePackModel.h +++ b/launcher/ui/pages/modplatform/TexturePackModel.h @@ -15,7 +15,7 @@ class TexturePackResourceModel : public ResourcePackResourceModel { public: TexturePackResourceModel(BaseInstance const& inst, ResourceAPI* api); - [[nodiscard]] inline ::Version maximumTexturePackVersion() const { return { "1.6" }; } + inline ::Version maximumTexturePackVersion() const { return { "1.6" }; } ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(const QModelIndex&) override; diff --git a/launcher/ui/pages/modplatform/TexturePackPage.h b/launcher/ui/pages/modplatform/TexturePackPage.h index 27fd8bcfc..262004dfd 100644 --- a/launcher/ui/pages/modplatform/TexturePackPage.h +++ b/launcher/ui/pages/modplatform/TexturePackPage.h @@ -35,9 +35,9 @@ class TexturePackResourcePage : public ResourcePackResourcePage { } //: The plural version of 'texture pack' - [[nodiscard]] inline QString resourcesString() const override { return tr("texture packs"); } + inline QString resourcesString() const override { return tr("texture packs"); } //: The singular version of 'texture packs' - [[nodiscard]] inline QString resourceString() const override { return tr("texture pack"); } + inline QString resourceString() const override { return tr("texture pack"); } protected: TexturePackResourcePage(TexturePackDownloadDialog* dialog, BaseInstance& instance) : ResourcePackResourcePage(dialog, instance) {} diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.h b/launcher/ui/pages/modplatform/atlauncher/AtlPage.h index 73460232b..556e90b1d 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.h @@ -68,7 +68,7 @@ class AtlPage : public QWidget, public ModpackProviderBasePage { /** Programatically set the term in the search bar. */ virtual void setSearchTerm(QString) override; /** Get the current term in the search bar. */ - [[nodiscard]] virtual QString getSerachTerm() const override; + virtual QString getSerachTerm() const override; private: void suggestCurrent(); diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.h b/launcher/ui/pages/modplatform/flame/FlameModel.h index 026f6d1ee..bfdd81810 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.h +++ b/launcher/ui/pages/modplatform/flame/FlameModel.h @@ -41,8 +41,8 @@ class ListModel : public QAbstractListModel { void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); void searchWithTerm(const QString& term, int sort, std::shared_ptr filter, bool filterChanged); - [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } - [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } + bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } private slots: void performPaginatedSearch(); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index 32b752bbe..19c8d4dbc 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -76,7 +76,7 @@ class FlamePage : public QWidget, public ModpackProviderBasePage { /** Programatically set the term in the search bar. */ virtual void setSearchTerm(QString) override; /** Get the current term in the search bar. */ - [[nodiscard]] virtual QString getSerachTerm() const override; + virtual QString getSerachTerm() const override; private: void suggestCurrent(); diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 5fffe6361..2cdc2910d 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -20,8 +20,8 @@ class FlameModModel : public ModModel { bool optedOut(const ModPlatform::IndexedVersion& ver) const override; private: - [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } + QString debugName() const override { return Flame::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Flame::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; @@ -41,8 +41,8 @@ class FlameResourcePackModel : public ResourcePackResourceModel { bool optedOut(const ModPlatform::IndexedVersion& ver) const override; private: - [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } + QString debugName() const override { return Flame::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Flame::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; @@ -61,8 +61,8 @@ class FlameTexturePackModel : public TexturePackResourceModel { bool optedOut(const ModPlatform::IndexedVersion& ver) const override; private: - [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } + QString debugName() const override { return Flame::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Flame::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; @@ -84,8 +84,8 @@ class FlameShaderPackModel : public ShaderPackResourceModel { bool optedOut(const ModPlatform::IndexedVersion& ver) const override; private: - [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } + QString debugName() const override { return Flame::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Flame::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; @@ -103,8 +103,8 @@ class FlameDataPackModel : public DataPackResourceModel { bool optedOut(const ModPlatform::IndexedVersion& ver) const override; private: - [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } + QString debugName() const override { return Flame::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Flame::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index 309e1e019..19f3731c7 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -86,15 +86,15 @@ class FlameModPage : public ModPage { FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance); ~FlameModPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Flame::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Flame::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Flame::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Flame::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } + inline auto displayName() const -> QString override { return Flame::displayName(); } + inline auto icon() const -> QIcon override { return Flame::icon(); } + inline auto id() const -> QString override { return Flame::id(); } + inline auto debugName() const -> QString override { return Flame::debugName(); } + inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; } + inline auto helpPage() const -> QString override { return "Mod-platform"; } void openUrl(const QUrl& url) override; std::unique_ptr createFilterWidget() override; @@ -118,15 +118,15 @@ class FlameResourcePackPage : public ResourcePackResourcePage { FlameResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance); ~FlameResourcePackPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Flame::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Flame::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Flame::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Flame::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } + inline auto displayName() const -> QString override { return Flame::displayName(); } + inline auto icon() const -> QIcon override { return Flame::icon(); } + inline auto id() const -> QString override { return Flame::id(); } + inline auto debugName() const -> QString override { return Flame::debugName(); } + inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + inline auto helpPage() const -> QString override { return ""; } void openUrl(const QUrl& url) override; }; @@ -143,15 +143,15 @@ class FlameTexturePackPage : public TexturePackResourcePage { FlameTexturePackPage(TexturePackDownloadDialog* dialog, BaseInstance& instance); ~FlameTexturePackPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Flame::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Flame::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Flame::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Flame::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } + inline auto displayName() const -> QString override { return Flame::displayName(); } + inline auto icon() const -> QIcon override { return Flame::icon(); } + inline auto id() const -> QString override { return Flame::id(); } + inline auto debugName() const -> QString override { return Flame::debugName(); } + inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + inline auto helpPage() const -> QString override { return ""; } void openUrl(const QUrl& url) override; }; @@ -168,15 +168,15 @@ class FlameShaderPackPage : public ShaderPackResourcePage { FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); ~FlameShaderPackPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Flame::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Flame::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Flame::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Flame::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } + inline auto displayName() const -> QString override { return Flame::displayName(); } + inline auto icon() const -> QIcon override { return Flame::icon(); } + inline auto id() const -> QString override { return Flame::id(); } + inline auto debugName() const -> QString override { return Flame::debugName(); } + inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + inline auto helpPage() const -> QString override { return ""; } void openUrl(const QUrl& url) override; }; @@ -195,15 +195,15 @@ class FlameDataPackPage : public DataPackResourcePage { FlameDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance); ~FlameDataPackPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Flame::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Flame::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Flame::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Flame::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } + inline auto displayName() const -> QString override { return Flame::displayName(); } + inline auto icon() const -> QIcon override { return Flame::icon(); } + inline auto id() const -> QString override { return Flame::id(); } + inline auto debugName() const -> QString override { return Flame::debugName(); } + inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + inline auto helpPage() const -> QString override { return ""; } void openUrl(const QUrl& url) override; }; diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h index 7afff5a9d..c00a93dfa 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h @@ -52,7 +52,7 @@ class ImportFTBPage : public QWidget, public ModpackProviderBasePage { /** Programatically set the term in the search bar. */ virtual void setSearchTerm(QString) override; /** Get the current term in the search bar. */ - [[nodiscard]] virtual QString getSerachTerm() const override; + virtual QString getSerachTerm() const override; private: void suggestCurrent(); diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.h b/launcher/ui/pages/modplatform/legacy_ftb/Page.h index 818000c05..fc789971f 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.h @@ -74,7 +74,7 @@ class Page : public QWidget, public ModpackProviderBasePage { /** Programatically set the term in the search bar. */ virtual void setSearchTerm(QString) override; /** Get the current term in the search bar. */ - [[nodiscard]] virtual QString getSerachTerm() const override; + virtual QString getSerachTerm() const override; private: void suggestCurrent(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index 640ddf688..cdd5c4e79 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -73,8 +73,8 @@ class ModpackListModel : public QAbstractListModel { void refresh(); void searchWithTerm(const QString& term, int sort, std::shared_ptr filter, bool filterChanged); - [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } - [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } + bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index d22a72e4e..77cc173dd 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -82,7 +82,7 @@ class ModrinthPage : public QWidget, public ModpackProviderBasePage { /** Programatically set the term in the search bar. */ virtual void setSearchTerm(QString) override; /** Get the current term in the search bar. */ - [[nodiscard]] virtual QString getSerachTerm() const override; + virtual QString getSerachTerm() const override; private slots: void onSelectionChanged(QModelIndex first, QModelIndex second); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index 6a5ba0382..7f68ed47d 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -35,8 +35,8 @@ class ModrinthModModel : public ModModel { ~ModrinthModModel() override = default; private: - [[nodiscard]] QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } + QString debugName() const override { return Modrinth::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; @@ -54,8 +54,8 @@ class ModrinthResourcePackModel : public ResourcePackResourceModel { ~ModrinthResourcePackModel() override = default; private: - [[nodiscard]] QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } + QString debugName() const override { return Modrinth::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; @@ -72,8 +72,8 @@ class ModrinthTexturePackModel : public TexturePackResourceModel { ~ModrinthTexturePackModel() override = default; private: - [[nodiscard]] QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } + QString debugName() const override { return Modrinth::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; @@ -90,8 +90,8 @@ class ModrinthShaderPackModel : public ShaderPackResourceModel { ~ModrinthShaderPackModel() override = default; private: - [[nodiscard]] QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } + QString debugName() const override { return Modrinth::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; @@ -108,8 +108,8 @@ class ModrinthDataPackModel : public DataPackResourceModel { ~ModrinthDataPackModel() override = default; private: - [[nodiscard]] QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - [[nodiscard]] QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } + QString debugName() const override { return Modrinth::debugName() + " (Model)"; } + QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h index a4c7344b5..cb0f4d85c 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h @@ -85,15 +85,15 @@ class ModrinthModPage : public ModPage { ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instance); ~ModrinthModPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Modrinth::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Modrinth::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Modrinth::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Modrinth::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } + inline auto displayName() const -> QString override { return Modrinth::displayName(); } + inline auto icon() const -> QIcon override { return Modrinth::icon(); } + inline auto id() const -> QString override { return Modrinth::id(); } + inline auto debugName() const -> QString override { return Modrinth::debugName(); } + inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; } + inline auto helpPage() const -> QString override { return "Mod-platform"; } std::unique_ptr createFilterWidget() override; @@ -114,15 +114,15 @@ class ModrinthResourcePackPage : public ResourcePackResourcePage { ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance); ~ModrinthResourcePackPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Modrinth::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Modrinth::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Modrinth::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Modrinth::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } + inline auto displayName() const -> QString override { return Modrinth::displayName(); } + inline auto icon() const -> QIcon override { return Modrinth::icon(); } + inline auto id() const -> QString override { return Modrinth::id(); } + inline auto debugName() const -> QString override { return Modrinth::debugName(); } + inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + inline auto helpPage() const -> QString override { return ""; } }; class ModrinthTexturePackPage : public TexturePackResourcePage { @@ -137,15 +137,15 @@ class ModrinthTexturePackPage : public TexturePackResourcePage { ModrinthTexturePackPage(TexturePackDownloadDialog* dialog, BaseInstance& instance); ~ModrinthTexturePackPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Modrinth::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Modrinth::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Modrinth::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Modrinth::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } + inline auto displayName() const -> QString override { return Modrinth::displayName(); } + inline auto icon() const -> QIcon override { return Modrinth::icon(); } + inline auto id() const -> QString override { return Modrinth::id(); } + inline auto debugName() const -> QString override { return Modrinth::debugName(); } + inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + inline auto helpPage() const -> QString override { return ""; } }; class ModrinthShaderPackPage : public ShaderPackResourcePage { @@ -160,15 +160,15 @@ class ModrinthShaderPackPage : public ShaderPackResourcePage { ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); ~ModrinthShaderPackPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Modrinth::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Modrinth::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Modrinth::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Modrinth::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } + inline auto displayName() const -> QString override { return Modrinth::displayName(); } + inline auto icon() const -> QIcon override { return Modrinth::icon(); } + inline auto id() const -> QString override { return Modrinth::id(); } + inline auto debugName() const -> QString override { return Modrinth::debugName(); } + inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + inline auto helpPage() const -> QString override { return ""; } }; class ModrinthDataPackPage : public DataPackResourcePage { @@ -183,15 +183,15 @@ class ModrinthDataPackPage : public DataPackResourcePage { ModrinthDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance); ~ModrinthDataPackPage() override = default; - [[nodiscard]] bool shouldDisplay() const override; + bool shouldDisplay() const override; - [[nodiscard]] inline auto displayName() const -> QString override { return Modrinth::displayName(); } - [[nodiscard]] inline auto icon() const -> QIcon override { return Modrinth::icon(); } - [[nodiscard]] inline auto id() const -> QString override { return Modrinth::id(); } - [[nodiscard]] inline auto debugName() const -> QString override { return Modrinth::debugName(); } - [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } + inline auto displayName() const -> QString override { return Modrinth::displayName(); } + inline auto icon() const -> QIcon override { return Modrinth::icon(); } + inline auto id() const -> QString override { return Modrinth::id(); } + inline auto debugName() const -> QString override { return Modrinth::debugName(); } + inline auto metaEntryBase() const -> QString override { return Modrinth::metaEntryBase(); } - [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + inline auto helpPage() const -> QString override { return ""; } }; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.h b/launcher/ui/pages/modplatform/technic/TechnicModel.h index 09e9294bb..4979000e9 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.h +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.h @@ -58,8 +58,8 @@ class ListModel : public QAbstractListModel { void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); void searchWithTerm(const QString& term); - [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } - [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } + bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } private slots: void searchRequestFinished(); diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index d1f691b22..71b6390ef 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -74,7 +74,7 @@ class TechnicPage : public QWidget, public ModpackProviderBasePage { /** Programatically set the term in the search bar. */ virtual void setSearchTerm(QString) override; /** Get the current term in the search bar. */ - [[nodiscard]] virtual QString getSerachTerm() const override; + virtual QString getSerachTerm() const override; private: void suggestCurrent(); diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index 2940d7ce7..e87c8b4c1 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -250,7 +250,7 @@ void WideBar::addContextMenuAction(QAction* action) m_context_menu_actions.append(action); } -[[nodiscard]] QByteArray WideBar::getVisibilityState() const +QByteArray WideBar::getVisibilityState() const { QByteArray state; diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index f4877a89a..68a052a23 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -35,7 +35,7 @@ class WideBar : public QToolBar { // Ideally we would use a QBitArray for this, but it doesn't support string conversion, // so using it in settings is very messy. - [[nodiscard]] QByteArray getVisibilityState() const; + QByteArray getVisibilityState() const; void setVisibilityState(QByteArray&&); void removeAction(QAction* action); @@ -50,8 +50,8 @@ class WideBar : public QToolBar { auto getMatching(QAction* act) -> QList::iterator; /** Used to distinguish between versions of the WideBar with different actions */ - [[nodiscard]] QByteArray getHash() const; - [[nodiscard]] bool checkHash(QByteArray const&) const; + QByteArray getHash() const; + bool checkHash(QByteArray const&) const; private: QList m_entries; diff --git a/tests/DummyResourceAPI.h b/tests/DummyResourceAPI.h index f8ab71e59..d5ae1392d 100644 --- a/tests/DummyResourceAPI.h +++ b/tests/DummyResourceAPI.h @@ -32,9 +32,9 @@ class DummyResourceAPI : public ResourceAPI { } DummyResourceAPI() : ResourceAPI() {} - [[nodiscard]] auto getSortingMethods() const -> QList override { return {}; } + auto getSortingMethods() const -> QList override { return {}; } - [[nodiscard]] Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&& callbacks) const override + Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&& callbacks) const override { auto task = makeShared(); QObject::connect(task.get(), &Task::succeeded, [callbacks] { diff --git a/tests/ResourceModel_test.cpp b/tests/ResourceModel_test.cpp index 30bb99fb8..c4ea1a20f 100644 --- a/tests/ResourceModel_test.cpp +++ b/tests/ResourceModel_test.cpp @@ -40,7 +40,7 @@ class DummyResourceModel : public ResourceModel { DummyResourceModel() : ResourceModel(new DummyResourceAPI) {} ~DummyResourceModel() {} - [[nodiscard]] auto metaEntryBase() const -> QString override { return ""; } + auto metaEntryBase() const -> QString override { return ""; } ResourceAPI::SearchArgs createSearchArguments() override { return {}; } ResourceAPI::VersionSearchArgs createVersionsArguments(const QModelIndex&) override { return {}; } From 6d19984873817f9520fdecb110211cc92b1496ec Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 7 Jul 2025 20:56:36 +0100 Subject: [PATCH 045/118] Add [[nodiscard]] guidelines Signed-off-by: TheKodeToad --- CONTRIBUTING.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5965f4d8e..fdc79faf2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributions Guidelines -## Code formatting +## Code style All files are formatted with `clang-format` using the configuration in `.clang-format`. Ensure it is run on changed files before committing! @@ -15,6 +15,11 @@ Please also follow the project's conventions for C++: - Global functions and non-`const` global variables should be formatted as `camelCase` without a prefix: `globalData`. - `const` global variables, macros, and enum constants should be formatted as `SCREAMING_SNAKE_CASE`: `LIGHT_GRAY`. - Avoid inventing acronyms or abbreviations especially for a name of multiple words - like `tp` for `texturePack`. +- Avoid using `[[nodiscard]]` unless ignoring the return value is likely to cause a bug in cases such as: + - A function allocates memory or another resource and the caller needs to clean it up. + - A function has side effects and an error status is returned. + - A function is likely be mistaken for having side effects. +- A plain getter is unlikely to cause confusion and adding `[[nodiscard]]` can create clutter and inconsistency. Most of these rules are included in the `.clang-tidy` file, so you can run `clang-tidy` to check for any violations. From 91abebbb596e5c57cc3f3beb946a3e00bb2145db Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Fri, 4 Jul 2025 02:13:47 -0400 Subject: [PATCH 046/118] build: let cmake know when we're cross compiling on msvc This (unsurprisingly) makes some things actually work as they're expected to when cross compiling, like windeployqt Signed-off-by: Seth Flynn --- cmake/windowsMSVCPreset.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/windowsMSVCPreset.json b/cmake/windowsMSVCPreset.json index 278f09b94..2cb996b81 100644 --- a/cmake/windowsMSVCPreset.json +++ b/cmake/windowsMSVCPreset.json @@ -20,7 +20,10 @@ "hidden": true, "inherits": [ "windows_msvc_base" - ] + ], + "cacheVariables": { + "CMAKE_SYSTEM_NAME": "${hostSystemName}" + } }, { "name": "windows_msvc_debug", From 1688db055ece8bc1430241e7b2ff68eddfb3ea6d Mon Sep 17 00:00:00 2001 From: seth Date: Fri, 2 May 2025 05:43:59 -0400 Subject: [PATCH 047/118] build: modernize launcher bundling Replaces fixup_bundle with Qt's deployment scripts and CMake's newer RUNTIME_DEPENDENCY_SET target, making it a bit easier to find and include linked dependencies with less code on our end Signed-off-by: seth --- CMakeLists.txt | 18 --- launcher/CMakeLists.txt | 212 ++++++------------------------ launcher/install_prereqs.cmake.in | 26 ---- 3 files changed, 43 insertions(+), 213 deletions(-) delete mode 100644 launcher/install_prereqs.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index a4d6df243..9ddf6b71a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -385,9 +385,6 @@ if(UNIX AND APPLE) set(RESOURCES_DEST_DIR "${Launcher_Name}.app/Contents/Resources") set(JARS_DEST_DIR "${Launcher_Name}.app/Contents/MacOS/jars") - # Apps to bundle - set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app") - # Mac bundle settings set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_DisplayName}") set(MACOSX_BUNDLE_INFO_STRING "${Launcher_DisplayName}: A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.") @@ -404,9 +401,6 @@ if(UNIX AND APPLE) set(MACOSX_SPARKLE_SHA256 "50612a06038abc931f16011d7903b8326a362c1074dabccb718404ce8e585f0b" CACHE STRING "SHA256 checksum for Sparkle release archive") set(MACOSX_SPARKLE_DIR "${CMAKE_BINARY_DIR}/frameworks/Sparkle") - # directories to look for dependencies - set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${MACOSX_SPARKLE_DIR}) - if(NOT MACOSX_SPARKLE_UPDATE_PUBLIC_KEY STREQUAL "" AND NOT MACOSX_SPARKLE_UPDATE_FEED_URL STREQUAL "") set(Launcher_ENABLE_UPDATER YES) endif() @@ -441,12 +435,6 @@ elseif(UNIX) set(PLUGIN_DEST_DIR "plugins") set(BUNDLE_DEST_DIR ".") set(RESOURCES_DEST_DIR ".") - - # Apps to bundle - set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${Launcher_APP_BINARY_NAME}") - - # directories to look for dependencies - set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) endif() if(Launcher_ManPage) @@ -464,12 +452,6 @@ elseif(WIN32) set(RESOURCES_DEST_DIR ".") set(JARS_DEST_DIR "jars") - # Apps to bundle - set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.exe") - - # directories to look for dependencies - set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - # install as bundle set(INSTALL_BUNDLE "full" CACHE STRING "Use fixup_bundle to bundle dependencies") else() diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 6204acabd..4555d6194 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1385,6 +1385,7 @@ if(DEFINED Launcher_APP_BINARY_DEFS) endif() install(TARGETS ${Launcher_Name} + RUNTIME_DEPENDENCY_SET LAUNCHER_DEPENDENCY_SET BUNDLE DESTINATION "." COMPONENT Runtime LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime @@ -1498,183 +1499,56 @@ endif() # Bundle utilities are used to complete the portable packages - they add all the libraries that would otherwise be missing on the target system. # NOTE: it seems that this absolutely has to be here, and nowhere else. if(INSTALL_BUNDLE STREQUAL "full") + if(WIN32) + set(QT_DEPLOY_TOOL_OPTIONS "--no-opengl-sw --no-quick-import --no-system-d3d-compiler --no-system-dxc-compiler --skip-plugin-types generic,networkinformation") + endif() + + qt_generate_deploy_script( + TARGET ${Launcher_Name} + OUTPUT_SCRIPT QT_DEPLOY_SCRIPT + CONTENT " + qt_deploy_runtime_dependencies( + EXECUTABLE ${BINARY_DEST_DIR}/$ + BIN_DIR ${BINARY_DEST_DIR} + LIBEXEC_DIR ${LIBRARY_DEST_DIR} + LIB_DIR ${LIBRARY_DEST_DIR} + PLUGINS_DIR ${PLUGIN_DEST_DIR} + NO_OVERWRITE + NO_TRANSLATIONS + NO_COMPILER_RUNTIME + DEPLOY_TOOL_OPTIONS ${QT_DEPLOY_TOOL_OPTIONS} + )" + ) + + # Bundle our linked dependencies + install(RUNTIME_DEPENDENCY_SET LAUNCHER_DEPENDENCY_SET + DIRECTORIES + ${CMAKE_SYSTEM_LIBRARY_PATH} + ${QT_LIBS_DIR} + ${QT_LIBEXECS_DIR} + PRE_EXCLUDE_REGEXES + "^(api-ms-win|ext-ms)-.*\\.dll$" + # FIXME: Why aren't these caught by the below regex??? + "^azure.*\\.dll$" + "^vcruntime.*\\.dll$" + POST_EXCLUDE_REGEXES + "system32" + LIBRARY DESTINATION ${LIBRARY_DEST_DIR} + RUNTIME DESTINATION ${BINARY_DEST_DIR} + FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} + ) + # Deploy Qt plugins + install(SCRIPT ${QT_DEPLOY_SCRIPT}) + # Add qt.conf - this makes Qt stop looking for things outside the bundle install( CODE "file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR}/qt.conf\" \" \")" COMPONENT Runtime ) - # add qtlogging.ini as a config file + # Add qtlogging.ini as a config file install( FILES "qtlogging.ini" DESTINATION ${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR} COMPONENT Runtime ) - # Bundle plugins - # Image formats - install( - DIRECTORY "${QT_PLUGINS_DIR}/imageformats" - CONFIGURATIONS Debug RelWithDebInfo "" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "tga|tiff|mng" EXCLUDE - ) - install( - DIRECTORY "${QT_PLUGINS_DIR}/imageformats" - CONFIGURATIONS Release MinSizeRel - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "tga|tiff|mng" EXCLUDE - REGEX "d\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - # Icon engines - install( - DIRECTORY "${QT_PLUGINS_DIR}/iconengines" - CONFIGURATIONS Debug RelWithDebInfo "" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "fontawesome" EXCLUDE - ) - install( - DIRECTORY "${QT_PLUGINS_DIR}/iconengines" - CONFIGURATIONS Release MinSizeRel - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "fontawesome" EXCLUDE - REGEX "d\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - # Platform plugins - install( - DIRECTORY "${QT_PLUGINS_DIR}/platforms" - CONFIGURATIONS Debug RelWithDebInfo "" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "minimal|linuxfb|offscreen" EXCLUDE - ) - install( - DIRECTORY "${QT_PLUGINS_DIR}/platforms" - CONFIGURATIONS Release MinSizeRel - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "minimal|linuxfb|offscreen" EXCLUDE - REGEX "[^2]d\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - # Style plugins - if(EXISTS "${QT_PLUGINS_DIR}/styles") - install( - DIRECTORY "${QT_PLUGINS_DIR}/styles" - CONFIGURATIONS Debug RelWithDebInfo "" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - ) - install( - DIRECTORY "${QT_PLUGINS_DIR}/styles" - CONFIGURATIONS Release MinSizeRel - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "d\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - endif() - # TLS plugins (Qt 6 only) - if(EXISTS "${QT_PLUGINS_DIR}/tls") - install( - DIRECTORY "${QT_PLUGINS_DIR}/tls" - CONFIGURATIONS Debug RelWithDebInfo "" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - PATTERN "*qcertonlybackend*" EXCLUDE - ) - install( - DIRECTORY "${QT_PLUGINS_DIR}/tls" - CONFIGURATIONS Release MinSizeRel - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "dd\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - PATTERN "*qcertonlybackend*" EXCLUDE - ) - endif() - # Wayland support - if(EXISTS "${QT_PLUGINS_DIR}/wayland-graphics-integration-client") - install( - DIRECTORY "${QT_PLUGINS_DIR}/wayland-graphics-integration-client" - CONFIGURATIONS Debug RelWithDebInfo "" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - ) - install( - DIRECTORY "${QT_PLUGINS_DIR}/wayland-graphics-integration-client" - CONFIGURATIONS Release MinSizeRel - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "dd\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - endif() - if(EXISTS "${QT_PLUGINS_DIR}/wayland-graphics-integration-server") - install( - DIRECTORY "${QT_PLUGINS_DIR}/wayland-graphics-integration-server" - CONFIGURATIONS Debug RelWithDebInfo "" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - ) - install( - DIRECTORY "${QT_PLUGINS_DIR}/wayland-graphics-integration-server" - CONFIGURATIONS Release MinSizeRel - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "dd\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - endif() - if(EXISTS "${QT_PLUGINS_DIR}/wayland-decoration-client") - install( - DIRECTORY "${QT_PLUGINS_DIR}/wayland-decoration-client" - CONFIGURATIONS Debug RelWithDebInfo "" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - ) - install( - DIRECTORY "${QT_PLUGINS_DIR}/wayland-decoration-client" - CONFIGURATIONS Release MinSizeRel - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "dd\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - endif() - if(EXISTS "${QT_PLUGINS_DIR}/wayland-shell-integration") - install( - DIRECTORY "${QT_PLUGINS_DIR}/wayland-shell-integration" - CONFIGURATIONS Debug RelWithDebInfo "" - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - ) - install( - DIRECTORY "${QT_PLUGINS_DIR}/wayland-shell-integration" - CONFIGURATIONS Release MinSizeRel - DESTINATION ${PLUGIN_DEST_DIR} - COMPONENT Runtime - REGEX "dd\\." EXCLUDE - REGEX "_debug\\." EXCLUDE - REGEX "\\.dSYM" EXCLUDE - ) - endif() - configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake" - @ONLY - ) - install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake" COMPONENT Runtime) endif() diff --git a/launcher/install_prereqs.cmake.in b/launcher/install_prereqs.cmake.in deleted file mode 100644 index acbce9650..000000000 --- a/launcher/install_prereqs.cmake.in +++ /dev/null @@ -1,26 +0,0 @@ -set(CMAKE_MODULE_PATH "@CMAKE_MODULE_PATH@") -file(GLOB_RECURSE QTPLUGINS "${CMAKE_INSTALL_PREFIX}/@PLUGIN_DEST_DIR@/*@CMAKE_SHARED_LIBRARY_SUFFIX@") -function(gp_resolved_file_type_override resolved_file type_var) - if(resolved_file MATCHES "^/(usr/)?lib/libQt") - set(${type_var} other PARENT_SCOPE) - elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libxcb-") - set(${type_var} other PARENT_SCOPE) - elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libicu") - set(${type_var} other PARENT_SCOPE) - elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libpng") - set(${type_var} other PARENT_SCOPE) - elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libproxy") - set(${type_var} other PARENT_SCOPE) - elseif((resolved_file MATCHES "^/(usr/)?lib(.+)?/libstdc\\+\\+") AND (UNIX AND NOT APPLE)) - set(${type_var} other PARENT_SCOPE) - endif() -endfunction() - -set(gp_tool "@CMAKE_GP_TOOL@") -set(gp_cmd_paths ${gp_cmd_paths} - "@CMAKE_GP_CMD_PATHS@" -) - -include(BundleUtilities) -fixup_bundle("@APPS@" "${QTPLUGINS}" "@DIRS@") - From f3b778342e99ff4d842ee06ac730873365ec7b74 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Tue, 8 Jul 2025 11:01:50 -0400 Subject: [PATCH 048/118] build(cmake): replace INSTALL_BUNDLE with install component Considering this doesn't affect the build, it has never made much sense for it to be a build option or require rereconfiguration of the project to change Signed-off-by: Seth Flynn --- CMakeLists.txt | 17 +++-------------- launcher/CMakeLists.txt | 17 +++++++++++------ 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ddf6b71a..73f1710b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -405,9 +405,6 @@ if(UNIX AND APPLE) set(Launcher_ENABLE_UPDATER YES) endif() - # install as bundle - set(INSTALL_BUNDLE "full" CACHE STRING "Use fixup_bundle to bundle dependencies") - # Add the icon install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns) @@ -418,9 +415,6 @@ elseif(UNIX) set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}") set(JARS_DEST_DIR "share/${Launcher_Name}") - # install as bundle with no dependencies included - set(INSTALL_BUNDLE "nodeps" CACHE STRING "Use fixup_bundle to bundle dependencies") - # Set RPATH SET(Launcher_BINARY_RPATH "$ORIGIN/") @@ -431,11 +425,9 @@ elseif(UNIX) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "share/${Launcher_Name}") - if (INSTALL_BUNDLE STREQUAL full) - set(PLUGIN_DEST_DIR "plugins") - set(BUNDLE_DEST_DIR ".") - set(RESOURCES_DEST_DIR ".") - endif() + set(PLUGIN_DEST_DIR "plugins") + set(BUNDLE_DEST_DIR ".") + set(RESOURCES_DEST_DIR ".") if(Launcher_ManPage) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6") @@ -451,9 +443,6 @@ elseif(WIN32) set(PLUGIN_DEST_DIR ".") set(RESOURCES_DEST_DIR ".") set(JARS_DEST_DIR "jars") - - # install as bundle - set(INSTALL_BUNDLE "full" CACHE STRING "Use fixup_bundle to bundle dependencies") else() message(FATAL_ERROR "Platform not supported") endif() diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 4555d6194..c1bc83b59 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1496,9 +1496,9 @@ if (UNIX AND APPLE AND Launcher_ENABLE_UPDATER) endif() #### The bundle mess! #### -# Bundle utilities are used to complete the portable packages - they add all the libraries that would otherwise be missing on the target system. +# Bundle utilities are used to complete packages for different platforms - they add all the libraries that would otherwise be missing on the target system. # NOTE: it seems that this absolutely has to be here, and nowhere else. -if(INSTALL_BUNDLE STREQUAL "full") +if(WIN32 OR (UNIX AND APPLE)) if(WIN32) set(QT_DEPLOY_TOOL_OPTIONS "--no-opengl-sw --no-quick-import --no-system-d3d-compiler --no-system-dxc-compiler --skip-plugin-types generic,networkinformation") endif() @@ -1521,7 +1521,9 @@ if(INSTALL_BUNDLE STREQUAL "full") ) # Bundle our linked dependencies - install(RUNTIME_DEPENDENCY_SET LAUNCHER_DEPENDENCY_SET + install( + RUNTIME_DEPENDENCY_SET LAUNCHER_DEPENDENCY_SET + COMPONENT bundle DIRECTORIES ${CMAKE_SYSTEM_LIBRARY_PATH} ${QT_LIBS_DIR} @@ -1538,17 +1540,20 @@ if(INSTALL_BUNDLE STREQUAL "full") FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} ) # Deploy Qt plugins - install(SCRIPT ${QT_DEPLOY_SCRIPT}) + install( + SCRIPT ${QT_DEPLOY_SCRIPT} + COMPONENT bundle + ) # Add qt.conf - this makes Qt stop looking for things outside the bundle install( CODE "file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR}/qt.conf\" \" \")" - COMPONENT Runtime + COMPONENT bundle ) # Add qtlogging.ini as a config file install( FILES "qtlogging.ini" DESTINATION ${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR} - COMPONENT Runtime + COMPONENT bundle ) endif() From a5f5d14538fcfa3d077b039ecc993aba0c07d710 Mon Sep 17 00:00:00 2001 From: seth Date: Mon, 5 May 2025 11:54:20 -0400 Subject: [PATCH 049/118] build(cmake): fallback to pkg-config discovery for tomlplusplus Some distributions of it (like in vcpkg *wink*) won't contain CMake files Signed-off-by: seth --- CMakeLists.txt | 8 ++++++++ launcher/CMakeLists.txt | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a4d6df243..10b0fcd08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -348,6 +348,14 @@ endif() if(NOT Launcher_FORCE_BUNDLED_LIBS) # Find toml++ find_package(tomlplusplus 3.2.0 QUIET) + # Fallback to pkg-config (if available) if CMake files aren't found + if(NOT tomlplusplus_FOUND) + find_package(PkgConfig) + if(PkgConfig_FOUND) + pkg_check_modules(tomlplusplus IMPORTED_TARGET tomlplusplus>=3.2.0) + endif() + endif() + # Find cmark find_package(cmark QUIET) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 6204acabd..7d96ffc38 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1309,12 +1309,16 @@ target_link_libraries(Launcher_logic Launcher_murmur2 nbt++ ${ZLIB_LIBRARIES} - tomlplusplus::tomlplusplus qdcss BuildConfig Qt${QT_VERSION_MAJOR}::Widgets qrcodegenerator ) +if(TARGET PkgConfig::tomlplusplus) + target_link_libraries(Launcher_logic PkgConfig::tomlplusplus) +else() + target_link_libraries(Launcher_logic tomlplusplus::tomlplusplus) +endif() if (UNIX AND NOT CYGWIN AND NOT APPLE) target_link_libraries(Launcher_logic From 7f78f6b85fd2621b3abb36c081d5b07e0b8c81fd Mon Sep 17 00:00:00 2001 From: seth Date: Thu, 1 May 2025 21:04:37 -0400 Subject: [PATCH 050/118] build: add support for vcpkg Signed-off-by: seth --- vcpkg-configuration.json | 14 ++++++++++++++ vcpkg.json | 10 ++++++++++ 2 files changed, 24 insertions(+) create mode 100644 vcpkg-configuration.json create mode 100644 vcpkg.json diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 000000000..610f6b31d --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,14 @@ +{ + "default-registry": { + "kind": "git", + "baseline": "0c4cf19224a049cf82f4521e29e39f7bd680440c", + "repository": "https://github.com/microsoft/vcpkg" + }, + "registries": [ + { + "kind": "artifact", + "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", + "name": "microsoft" + } + ] +} diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 000000000..4abf8d1b7 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,10 @@ +{ + "dependencies": [ + "bzip2", + "cmark", + { "name": "ecm", "host": true }, + { "name": "pkgconf", "host": true }, + "tomlplusplus", + "zlib" + ] +} From 463cf431610a04a3c7ec4a90f4d83389fdbae2c1 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Mon, 5 May 2025 13:00:20 -0400 Subject: [PATCH 051/118] ci(setup-deps/windows): use vcpkg for msvc Signed-off-by: Seth Flynn --- .../setup-dependencies/windows/action.yml | 25 +++++++++++++++++++ .github/workflows/build.yml | 4 +++ 2 files changed, 29 insertions(+) diff --git a/.github/actions/setup-dependencies/windows/action.yml b/.github/actions/setup-dependencies/windows/action.yml index 0a643f583..e899c36d6 100644 --- a/.github/actions/setup-dependencies/windows/action.yml +++ b/.github/actions/setup-dependencies/windows/action.yml @@ -25,6 +25,31 @@ runs: arch: ${{ inputs.vcvars-arch }} vsversion: 2022 + - name: Setup vcpkg cache (MSVC) + if: ${{ inputs.msystem == '' && inputs.build-type == 'Debug' }} + shell: pwsh + env: + USERNAME: ${{ github.repository_owner }} + FEED_URL: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json + run: | + .$(vcpkg fetch nuget) ` + sources add ` + -Source "$env:FEED_URL" ` + -StorePasswordInClearText ` + -Name GitHubPackages ` + -UserName "$env:USERNAME" ` + -Password "$env:GITHUB_TOKEN" + .$(vcpkg fetch nuget) ` + setapikey "$env:GITHUB_TOKEN" ` + -Source "$env:FEED_URL" + Write-Output "VCPKG_BINARY_SOURCES=clear;nuget,$env:FEED_URL,readwrite" >> "$GITHUB_ENV" + + - name: Setup vcpkg environment (MSVC) + if: ${{ inputs.msystem == '' }} + shell: bash + run: | + echo "CMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" >> "$GITHUB_ENV" + - name: Setup MSYS2 (MinGW) if: ${{ inputs.msystem != '' }} uses: msys2/setup-msys2@v2 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15de6f70f..b8ba57a45 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -69,6 +69,10 @@ jobs: build: name: Build (${{ matrix.artifact-name }}) + permissions: + # Required for vcpkg binary cache + packages: write + strategy: fail-fast: false matrix: From 20a833e1b952ed75480ca2ad8cdecdce3ed0ab4c Mon Sep 17 00:00:00 2001 From: matthewperiut Date: Thu, 10 Jul 2025 11:07:17 -0400 Subject: [PATCH 052/118] Add "Babric" and "Babric (BTA)" as shown on Modrinth. Add "Show More" button to allow for space efficiency and readiness to add all other Modrinth modloader types. Signed-off-by: matthewperiut --- launcher/modplatform/ModIndex.cpp | 10 +++- launcher/modplatform/ModIndex.h | 4 +- launcher/modplatform/flame/FlameAPI.h | 2 + .../import_ftb/PackInstallTask.cpp | 4 ++ launcher/modplatform/modrinth/ModrinthAPI.h | 4 +- launcher/ui/widgets/ModFilterWidget.cpp | 24 ++++++++-- launcher/ui/widgets/ModFilterWidget.h | 1 + launcher/ui/widgets/ModFilterWidget.ui | 46 ++++++++++++++++++- 8 files changed, 85 insertions(+), 10 deletions(-) diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index e18ccaefa..edb5e5aa1 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -31,7 +31,7 @@ static const QMap s_indexed_version_ty { "alpha", IndexedVersionType::VersionType::Alpha } }; -static const QList loaderList = { NeoForge, Forge, Cauldron, LiteLoader, Quilt, Fabric }; +static const QList loaderList = { NeoForge, Forge, Cauldron, LiteLoader, Quilt, Fabric, Babric, BTA }; QList modLoaderTypesToList(ModLoaderTypes flags) { @@ -129,6 +129,10 @@ auto getModLoaderAsString(ModLoaderType type) -> const QString return "quilt"; case DataPack: return "datapack"; + case Babric: + return "babric"; + case BTA: + return "bta-babric"; default: break; } @@ -149,6 +153,10 @@ auto getModLoaderFromString(QString type) -> ModLoaderType return Fabric; if (type == "quilt") return Quilt; + if (type == "babric") + return Babric; + if (type == "bta-babric") + return BTA; return {}; } diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index cfe4eba75..7c4d1c885 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -36,7 +36,9 @@ enum ModLoaderType { LiteLoader = 1 << 3, Fabric = 1 << 4, Quilt = 1 << 5, - DataPack = 1 << 6 + DataPack = 1 << 6, + Babric = 1 << 7, + BTA = 1 << 8 }; Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType) QList modLoaderTypesToList(ModLoaderTypes flags); diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 316d2e9c9..c578f7ae6 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -71,6 +71,8 @@ class FlameAPI : public NetworkResourceAPI { case ModPlatform::NeoForge: return 6; case ModPlatform::DataPack: + case ModPlatform::Babric: + case ModPlatform::BTA: break; // not supported } return 0; diff --git a/launcher/modplatform/import_ftb/PackInstallTask.cpp b/launcher/modplatform/import_ftb/PackInstallTask.cpp index 7cb8b6ebc..9ddca008d 100644 --- a/launcher/modplatform/import_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/import_ftb/PackInstallTask.cpp @@ -91,6 +91,10 @@ void PackInstallTask::copySettings() break; case ModPlatform::DataPack: break; + case ModPlatform::Babric: + break; + case ModPlatform::BTA: + break; } components->saveNow(); diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 7c2592256..3c2da0651 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -43,7 +43,7 @@ class ModrinthAPI : public NetworkResourceAPI { { QStringList l; for (auto loader : { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Fabric, ModPlatform::Quilt, ModPlatform::LiteLoader, - ModPlatform::DataPack }) { + ModPlatform::DataPack, ModPlatform::Babric, ModPlatform::BTA }) { if (types & loader) { l << getModLoaderAsString(loader); } @@ -202,7 +202,7 @@ class ModrinthAPI : public NetworkResourceAPI { static inline auto validateModLoaders(ModPlatform::ModLoaderTypes loaders) -> bool { return loaders & (ModPlatform::NeoForge | ModPlatform::Forge | ModPlatform::Fabric | ModPlatform::Quilt | ModPlatform::LiteLoader | - ModPlatform::DataPack); + ModPlatform::DataPack | ModPlatform::Babric | ModPlatform::BTA); } [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index 3c6a2db07..654eb75b1 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -149,10 +149,16 @@ ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, bool extended) connect(ui->forge, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); connect(ui->fabric, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); connect(ui->quilt, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); - if (extended) - connect(ui->liteLoader, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); - else - ui->liteLoader->setVisible(false); + connect(ui->liteLoader, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); + connect(ui->babric, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); + connect(ui->btaBabric, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); + + connect(ui->showMoreButton, &QPushButton::clicked, this, &ModFilterWidget::onShowMoreClicked); + + if (!extended) { + ui->showMoreButton->setVisible(false); + ui->extendedModLoadersWidget->setVisible(false); + } if (extended) { connect(ui->clientSide, &QCheckBox::stateChanged, this, &ModFilterWidget::onSideFilterChanged); @@ -279,6 +285,10 @@ void ModFilterWidget::onLoadersFilterChanged() loaders |= ModPlatform::Quilt; if (ui->liteLoader->isChecked()) loaders |= ModPlatform::LiteLoader; + if (ui->babric->isChecked()) + loaders |= ModPlatform::Babric; + if (ui->btaBabric->isChecked()) + loaders |= ModPlatform::BTA; m_filter_changed = loaders != m_filter->loaders; m_filter->loaders = loaders; if (m_filter_changed) @@ -381,4 +391,10 @@ void ModFilterWidget::onReleaseFilterChanged() emit filterChanged(); } +void ModFilterWidget::onShowMoreClicked() +{ + ui->extendedModLoadersWidget->setVisible(true); + ui->showMoreButton->setVisible(false); +} + #include "ModFilterWidget.moc" diff --git a/launcher/ui/widgets/ModFilterWidget.h b/launcher/ui/widgets/ModFilterWidget.h index be60ba70a..8a858fd30 100644 --- a/launcher/ui/widgets/ModFilterWidget.h +++ b/launcher/ui/widgets/ModFilterWidget.h @@ -110,6 +110,7 @@ class ModFilterWidget : public QTabWidget { void onShowAllVersionsChanged(); void onOpenSourceFilterChanged(); void onReleaseFilterChanged(); + void onShowMoreClicked(); private: Ui::ModFilterWidget* ui; diff --git a/launcher/ui/widgets/ModFilterWidget.ui b/launcher/ui/widgets/ModFilterWidget.ui index 788202714..87d9af2e3 100644 --- a/launcher/ui/widgets/ModFilterWidget.ui +++ b/launcher/ui/widgets/ModFilterWidget.ui @@ -122,12 +122,54 @@
- + - LiteLoader + Show More + + + + false + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + LiteLoader + + + + + + + Babric + + + + + + + BTA (Babric) + + + + + + From 9ce6d3571e8924f7a27daaf8c2e301e9d60d47a1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 22:00:35 +0000 Subject: [PATCH 053/118] chore(deps): update cachix/install-nix-action digest to cebd211 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 123028ff2..ce86ff798 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31 + - uses: cachix/install-nix-action@cebd211ec2008b83bda8fb0b21c3c072f004fe04 # v31 - uses: DeterminateSystems/update-flake-lock@v26 with: From 5fb6022b472f454a573be97d0f03272b643badc2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 12 Jul 2025 13:50:35 +0000 Subject: [PATCH 054/118] chore(deps): update cachix/install-nix-action digest to f0fe604 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index ce86ff798..123028ff2 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@cebd211ec2008b83bda8fb0b21c3c072f004fe04 # v31 + - uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31 - uses: DeterminateSystems/update-flake-lock@v26 with: From f5fffd27ab466514fd41ba757f9bb7525de775cc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 13 Jul 2025 00:31:57 +0000 Subject: [PATCH 055/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/5c724ed1388e53cc231ed98330a60eb2f7be4be3?narHash=sha256-xVNy/XopSfIG9c46nRmPaKfH1Gn/56vQ8%2B%2BxWA8itO4%3D' (2025-07-04) → 'github:NixOS/nixpkgs/9807714d6944a957c2e036f84b0ff8caf9930bc0?narHash=sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X%2BxgOL0%3D' (2025-07-08) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 17b77e22b..b5f6258e1 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1751637120, - "narHash": "sha256-xVNy/XopSfIG9c46nRmPaKfH1Gn/56vQ8++xWA8itO4=", + "lastModified": 1751984180, + "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5c724ed1388e53cc231ed98330a60eb2f7be4be3", + "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0", "type": "github" }, "original": { From 9210d68ed1df8f6fe84d3bb51682a983154b440e Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Sun, 13 Jul 2025 15:24:01 -0400 Subject: [PATCH 056/118] ci(setup-deps/windows): try to fix vcpkg binary cache auth Signed-off-by: Seth Flynn --- .github/actions/setup-dependencies/windows/action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-dependencies/windows/action.yml b/.github/actions/setup-dependencies/windows/action.yml index e899c36d6..97033747e 100644 --- a/.github/actions/setup-dependencies/windows/action.yml +++ b/.github/actions/setup-dependencies/windows/action.yml @@ -30,6 +30,7 @@ runs: shell: pwsh env: USERNAME: ${{ github.repository_owner }} + GITHUB_TOKEN: ${{ github.token }} FEED_URL: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json run: | .$(vcpkg fetch nuget) ` @@ -42,7 +43,7 @@ runs: .$(vcpkg fetch nuget) ` setapikey "$env:GITHUB_TOKEN" ` -Source "$env:FEED_URL" - Write-Output "VCPKG_BINARY_SOURCES=clear;nuget,$env:FEED_URL,readwrite" >> "$GITHUB_ENV" + "VCPKG_BINARY_SOURCES=clear;nuget,$env:FEED_URL,readwrite" | Out-File -Append $env:GITHUB_ENV - name: Setup vcpkg environment (MSVC) if: ${{ inputs.msystem == '' }} From 4614d683b3593022c4d07c97fea2434cd33c3451 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Sun, 13 Jul 2025 15:30:55 -0400 Subject: [PATCH 057/118] ci(macos): use vcpkg Signed-off-by: Seth Flynn --- .github/actions/setup-dependencies/action.yml | 2 ++ .../setup-dependencies/macos/action.yml | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/.github/actions/setup-dependencies/action.yml b/.github/actions/setup-dependencies/action.yml index e61509c44..6c718f9e3 100644 --- a/.github/actions/setup-dependencies/action.yml +++ b/.github/actions/setup-dependencies/action.yml @@ -42,6 +42,8 @@ runs: - name: Setup macOS dependencies if: ${{ runner.os == 'macOS' }} uses: ./.github/actions/setup-dependencies/macos + with: + build-type: ${{ inputs.build-type }} - name: Setup Windows dependencies if: ${{ runner.os == 'Windows' }} diff --git a/.github/actions/setup-dependencies/macos/action.yml b/.github/actions/setup-dependencies/macos/action.yml index dcbb308c2..6fc3ed3bf 100644 --- a/.github/actions/setup-dependencies/macos/action.yml +++ b/.github/actions/setup-dependencies/macos/action.yml @@ -1,5 +1,11 @@ name: Setup macOS dependencies +inputs: + build-type: + description: Type for the build + required: true + default: Debug + runs: using: composite @@ -14,3 +20,29 @@ runs: shell: bash run: | echo "JAVA_HOME=$(/usr/libexec/java_home -v 17)" >> "$GITHUB_ENV" + + - name: Setup vcpkg cache + if: ${{ inputs.build-type == 'Debug' }} + shell: bash + env: + USERNAME: ${{ github.repository_owner }} + GITHUB_TOKEN: ${{ github.token }} + FEED_URL: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json + run: | + mono `vcpkg fetch nuget | tail -n 1` \ + sources add \ + -Source "$FEED_URL" \ + -StorePasswordInClearText \ + -Name GitHubPackages \ + -UserName "$USERNAME" \ + -Password "$GITHUB_TOKEN" + mono `vcpkg fetch nuget | tail -n 1` \ + setapikey "$GITHUB_TOKEN" \ + -Source "$FEED_URL" + echo "VCPKG_BINARY_SOURCES=clear;nuget,$FEED_URL,readwrite" >> "$GITHUB_ENV" + + - name: Setup vcpkg environment + if: ${{ inputs.build-type == 'Debug' }} + shell: bash + run: | + echo "CMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" >> "$GITHUB_ENV" From 5c8ce8db664507c5b1aa7d6e38e98f0ea646ede3 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Sun, 13 Jul 2025 15:49:26 -0400 Subject: [PATCH 058/118] build(vcpkg): add univesal-osx triplet vcpkg doesn't officially support universal binaries, but this should function as a workaround until it does one day Signed-off-by: Seth Flynn --- cmake/macosPreset.json | 3 ++- cmake/vcpkg-triplets/universal-osx.cmake | 8 ++++++++ vcpkg-configuration.json | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 cmake/vcpkg-triplets/universal-osx.cmake diff --git a/cmake/macosPreset.json b/cmake/macosPreset.json index de503d7a2..9098f9a9a 100644 --- a/cmake/macosPreset.json +++ b/cmake/macosPreset.json @@ -22,7 +22,8 @@ "macos_base" ], "cacheVariables": { - "CMAKE_OSX_ARCHITECTURES": "x86_64;arm64" + "CMAKE_OSX_ARCHITECTURES": "x86_64;arm64", + "VCPKG_TARGET_TRIPLET": "universal-osx" } }, { diff --git a/cmake/vcpkg-triplets/universal-osx.cmake b/cmake/vcpkg-triplets/universal-osx.cmake new file mode 100644 index 000000000..1c91a5650 --- /dev/null +++ b/cmake/vcpkg-triplets/universal-osx.cmake @@ -0,0 +1,8 @@ +# See https://github.com/microsoft/vcpkg/discussions/19454 +# NOTE: Try to keep in sync with default arm64-osx definition +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE static) + +set(VCPKG_CMAKE_SYSTEM_NAME Darwin) +set(VCPKG_OSX_ARCHITECTURES "arm64;x86_64") diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json index 610f6b31d..3a59b2658 100644 --- a/vcpkg-configuration.json +++ b/vcpkg-configuration.json @@ -10,5 +10,8 @@ "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", "name": "microsoft" } + ], + "overlay-triplets": [ + "./cmake/vcpkg-triplets" ] } From 3cc83626629becc5e9a1d95440c20df292374b42 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 03:24:25 +0000 Subject: [PATCH 059/118] chore(deps): update determinatesystems/nix-installer-action action to v19 --- .github/workflows/nix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index ecd71977e..6c7b2dac2 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -110,7 +110,7 @@ jobs: ref: ${{ steps.merge-commit.outputs.merge-commit-sha || github.sha }} - name: Install Nix - uses: DeterminateSystems/nix-installer-action@v18 + uses: DeterminateSystems/nix-installer-action@v19 with: determinate: ${{ env.USE_DETERMINATE }} From 49daf6211417a13fd2989998c626b07bc1277d1c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 03:24:29 +0000 Subject: [PATCH 060/118] chore(deps): update determinatesystems/update-flake-lock action to v27 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 123028ff2..de341b517 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31 - - uses: DeterminateSystems/update-flake-lock@v26 + - uses: DeterminateSystems/update-flake-lock@v27 with: commit-msg: "chore(nix): update lockfile" pr-title: "chore(nix): update lockfile" From 3e65d3a9b5edcc5c1353686fe00b56d266db4e6e Mon Sep 17 00:00:00 2001 From: Kenneth Chew <79120643+kthchew@users.noreply.github.com> Date: Wed, 16 Jul 2025 00:28:28 -0400 Subject: [PATCH 061/118] Apply selected style to window elements on macOS Qt doesn't apply the proper style to elements such as the title bar or text shadows, so this must be done in native code. Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com> --- launcher/CMakeLists.txt | 7 +++ launcher/ui/themes/ThemeManager.cpp | 8 ++++ launcher/ui/themes/ThemeManager.h | 9 ++++ launcher/ui/themes/ThemeManager.mm | 67 +++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 launcher/ui/themes/ThemeManager.mm diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ff6a9ab2a..5c23aae0d 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1178,6 +1178,13 @@ SET(LAUNCHER_SOURCES ui/instanceview/VisualGroup.h ) +if (APPLE) + set(LAUNCHER_SOURCES + ${LAUNCHER_SOURCES} + ui/themes/ThemeManager.mm + ) +endif() + if (NOT Apple) set(LAUNCHER_SOURCES ${LAUNCHER_SOURCES} diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 30a1fe7be..c1af63dc8 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -174,6 +174,13 @@ void ThemeManager::initializeWidgets() themeDebugLog() << "<> Widget themes initialized."; } +#ifndef Q_OS_MACOS +void ThemeManager::setTitlebarColorOnMac(WId windowId, QColor color) +{} +void ThemeManager::setTitlebarColorOfAllWindowsOnMac(QColor color) +{} +#endif + QList ThemeManager::getValidIconThemes() { QList ret; @@ -247,6 +254,7 @@ void ThemeManager::setApplicationTheme(const QString& name, bool initial) auto& theme = themeIter->second; themeDebugLog() << "applying theme" << theme->name(); theme->apply(initial); + setTitlebarColorOfAllWindowsOnMac(qApp->palette().window().color()); m_logColors = theme->logColorScheme(); } else { diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 8de7562d1..dd33523d8 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -81,6 +81,15 @@ class ThemeManager { void initializeIcons(); void initializeWidgets(); + // On non-Mac systems, this is a no-op. + void setTitlebarColorOnMac(WId windowId, QColor color); + // This also will set the titlebar color of newly opened windows after this method is called. + // On non-Mac systems, this is a no-op. + void setTitlebarColorOfAllWindowsOnMac(QColor color); +#ifdef Q_OS_MACOS + NSObject* m_windowTitlebarObserver = nullptr; +#endif + const QStringList builtinIcons{ "pe_colored", "pe_light", "pe_dark", "pe_blue", "breeze_light", "breeze_dark", "OSX", "iOS", "flat", "flat_white", "multimc" }; }; diff --git a/launcher/ui/themes/ThemeManager.mm b/launcher/ui/themes/ThemeManager.mm new file mode 100644 index 000000000..21b3d8e35 --- /dev/null +++ b/launcher/ui/themes/ThemeManager.mm @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2025 Kenneth Chew <79120643+kthchew@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ThemeManager.h" + +#include + +void ThemeManager::setTitlebarColorOnMac(WId windowId, QColor color) +{ + if (windowId == 0) { + return; + } + + NSView* view = (NSView*)windowId; + NSWindow* window = [view window]; + window.titlebarAppearsTransparent = YES; + window.backgroundColor = [NSColor colorWithRed:color.redF() green:color.greenF() blue:color.blueF() alpha:color.alphaF()]; + + // Unfortunately there seems to be no easy way to set the titlebar text color. + // The closest we can do without dubious hacks is set the dark/light mode state based on the brightness of the + // background color, which should at least make the text readable even if we can't use the theme's text color. + // It's a good idea to set this anyway since it also affects some other UI elements like text shadows (PrismLauncher#3825). + if (color.lightnessF() < 0.5) { + window.appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; + } else { + window.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua]; + } +} + +void ThemeManager::setTitlebarColorOfAllWindowsOnMac(QColor color) +{ + NSArray* windows = [NSApp windows]; + for (NSWindow* window : windows) { + setTitlebarColorOnMac((WId)window.contentView, color); + } + + // We want to change the titlebar color of newly opened windows as well. + // There's no notification for when a new window is opened, but we can set the color when a window switches + // from occluded to visible, which also fires on open. + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + if (m_windowTitlebarObserver) { + [center removeObserver:m_windowTitlebarObserver]; + m_windowTitlebarObserver = nil; + } + m_windowTitlebarObserver = [center addObserverForName:NSWindowDidChangeOcclusionStateNotification + object:nil + queue:[NSOperationQueue mainQueue] + usingBlock:^(NSNotification* notification) { + NSWindow* window = notification.object; + setTitlebarColorOnMac((WId)window.contentView, color); + }]; +} From 677a7d7a052f2f200eac28ddf822da493d1e2ac1 Mon Sep 17 00:00:00 2001 From: Kenneth Chew <79120643+kthchew@users.noreply.github.com> Date: Wed, 16 Jul 2025 01:10:05 -0400 Subject: [PATCH 062/118] Unregister window observer before theme manager is deallocated Technically this probably isn't actually necessary since ThemeManager looks like it should remain allocated until the program quits, but... Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com> --- launcher/ui/themes/ThemeManager.cpp | 7 +++++++ launcher/ui/themes/ThemeManager.h | 3 +++ launcher/ui/themes/ThemeManager.mm | 14 ++++++++++---- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index c1af63dc8..a7076da5a 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -50,6 +50,11 @@ ThemeManager::ThemeManager() initializeCatPacks(); } +ThemeManager::~ThemeManager() +{ + stopSettingNewWindowColorsOnMac(); +} + /// @brief Adds the Theme to the list of themes /// @param theme The Theme to add /// @return Theme ID @@ -179,6 +184,8 @@ void ThemeManager::setTitlebarColorOnMac(WId windowId, QColor color) {} void ThemeManager::setTitlebarColorOfAllWindowsOnMac(QColor color) {} +void ThemeManager::stopSettingNewWindowColorsOnMac() +{} #endif QList ThemeManager::getValidIconThemes() diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index dd33523d8..8baa88627 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -39,6 +39,7 @@ inline auto themeWarningLog() class ThemeManager { public: ThemeManager(); + ~ThemeManager(); QList getValidIconThemes(); QList getValidApplicationThemes(); @@ -86,6 +87,8 @@ class ThemeManager { // This also will set the titlebar color of newly opened windows after this method is called. // On non-Mac systems, this is a no-op. void setTitlebarColorOfAllWindowsOnMac(QColor color); + // On non-Mac systems, this is a no-op. + void stopSettingNewWindowColorsOnMac(); #ifdef Q_OS_MACOS NSObject* m_windowTitlebarObserver = nullptr; #endif diff --git a/launcher/ui/themes/ThemeManager.mm b/launcher/ui/themes/ThemeManager.mm index 21b3d8e35..d9fc291b6 100644 --- a/launcher/ui/themes/ThemeManager.mm +++ b/launcher/ui/themes/ThemeManager.mm @@ -53,10 +53,7 @@ void ThemeManager::setTitlebarColorOfAllWindowsOnMac(QColor color) // There's no notification for when a new window is opened, but we can set the color when a window switches // from occluded to visible, which also fires on open. NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; - if (m_windowTitlebarObserver) { - [center removeObserver:m_windowTitlebarObserver]; - m_windowTitlebarObserver = nil; - } + stopSettingNewWindowColorsOnMac(); m_windowTitlebarObserver = [center addObserverForName:NSWindowDidChangeOcclusionStateNotification object:nil queue:[NSOperationQueue mainQueue] @@ -65,3 +62,12 @@ void ThemeManager::setTitlebarColorOfAllWindowsOnMac(QColor color) setTitlebarColorOnMac((WId)window.contentView, color); }]; } + +void ThemeManager::stopSettingNewWindowColorsOnMac() +{ + if (m_windowTitlebarObserver) { + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + [center removeObserver:m_windowTitlebarObserver]; + m_windowTitlebarObserver = nil; + } +} From 78dc42f4dd3ba76dcf2e3cdbd55f8cbb7e7811c6 Mon Sep 17 00:00:00 2001 From: clague <93119153+clague@users.noreply.github.com> Date: Wed, 16 Jul 2025 14:56:44 +0800 Subject: [PATCH 063/118] fix grammar Co-authored-by: Seth Flynn Signed-off-by: clague <93119153+clague@users.noreply.github.com> --- launcher/ui/pages/global/APIPage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/global/APIPage.ui b/launcher/ui/pages/global/APIPage.ui index cc36ff7b2..b918ae29e 100644 --- a/launcher/ui/pages/global/APIPage.ui +++ b/launcher/ui/pages/global/APIPage.ui @@ -138,7 +138,7 @@ - You can set this to another server if you have problem in downloading assets. + You can set this to another server if you have problems with downloading assets. Qt::RichText From 9a51cd55df95c0d99423f7e358775b7f82dc4e76 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 24 Mar 2025 23:06:53 +0200 Subject: [PATCH 064/118] make universal resource type Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 2 + .../mod/tasks/LocalResourceParse.cpp | 30 ++++---------- .../minecraft/mod/tasks/LocalResourceParse.h | 12 +----- launcher/modplatform/ModIndex.h | 2 - launcher/modplatform/ResourceAPI.h | 1 + launcher/modplatform/ResourceType.cpp | 41 +++++++++++++++++++ launcher/modplatform/ResourceType.h | 39 ++++++++++++++++++ .../modplatform/flame/FileResolvingTask.cpp | 14 +++---- launcher/modplatform/flame/FlameAPI.cpp | 2 +- launcher/modplatform/flame/FlameAPI.h | 10 ++--- .../flame/FlameInstanceCreationTask.cpp | 16 ++++---- launcher/modplatform/flame/PackManifest.h | 4 +- launcher/modplatform/modrinth/ModrinthAPI.h | 10 ++--- launcher/ui/MainWindow.cpp | 16 ++++---- launcher/ui/dialogs/ImportResourceDialog.cpp | 5 ++- launcher/ui/dialogs/ImportResourceDialog.h | 6 +-- .../ui/pages/modplatform/DataPackModel.cpp | 2 +- launcher/ui/pages/modplatform/ModModel.cpp | 2 +- .../pages/modplatform/ResourcePackModel.cpp | 2 +- .../ui/pages/modplatform/ShaderPackModel.cpp | 2 +- .../ui/pages/modplatform/flame/FlameModel.cpp | 2 +- .../ui/pages/modplatform/flame/FlamePage.cpp | 2 +- .../modplatform/modrinth/ModrinthModel.cpp | 2 +- 23 files changed, 143 insertions(+), 81 deletions(-) create mode 100644 launcher/modplatform/ResourceType.cpp create mode 100644 launcher/modplatform/ResourceType.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ff6a9ab2a..79cbd90fc 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -494,6 +494,8 @@ set(META_SOURCES set(API_SOURCES modplatform/ModIndex.h modplatform/ModIndex.cpp + modplatform/ResourceType.h + modplatform/ResourceType.cpp modplatform/ResourceAPI.h diff --git a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp index e309b2105..39e8a321b 100644 --- a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp @@ -28,50 +28,38 @@ #include "LocalShaderPackParseTask.h" #include "LocalTexturePackParseTask.h" #include "LocalWorldSaveParseTask.h" - -static const QMap s_packed_type_names = { { PackedResourceType::ResourcePack, QObject::tr("resource pack") }, - { PackedResourceType::TexturePack, QObject::tr("texture pack") }, - { PackedResourceType::DataPack, QObject::tr("data pack") }, - { PackedResourceType::ShaderPack, QObject::tr("shader pack") }, - { PackedResourceType::WorldSave, QObject::tr("world save") }, - { PackedResourceType::Mod, QObject::tr("mod") }, - { PackedResourceType::UNKNOWN, QObject::tr("unknown") } }; +#include "modplatform/ResourceType.h" namespace ResourceUtils { -PackedResourceType identify(QFileInfo file) +ModPlatform::ResourceType identify(QFileInfo file) { if (file.exists() && file.isFile()) { if (ModUtils::validate(file)) { // mods can contain resource and data packs so they must be tested first qDebug() << file.fileName() << "is a mod"; - return PackedResourceType::Mod; + return ModPlatform::ResourceType::Mod; } else if (DataPackUtils::validateResourcePack(file)) { qDebug() << file.fileName() << "is a resource pack"; - return PackedResourceType::ResourcePack; + return ModPlatform::ResourceType::ResourcePack; } else if (TexturePackUtils::validate(file)) { qDebug() << file.fileName() << "is a pre 1.6 texture pack"; - return PackedResourceType::TexturePack; + return ModPlatform::ResourceType::TexturePack; } else if (DataPackUtils::validate(file)) { qDebug() << file.fileName() << "is a data pack"; - return PackedResourceType::DataPack; + return ModPlatform::ResourceType::DataPack; } else if (WorldSaveUtils::validate(file)) { qDebug() << file.fileName() << "is a world save"; - return PackedResourceType::WorldSave; + return ModPlatform::ResourceType::World; } else if (ShaderPackUtils::validate(file)) { qDebug() << file.fileName() << "is a shader pack"; - return PackedResourceType::ShaderPack; + return ModPlatform::ResourceType::ShaderPack; } else { qDebug() << "Can't Identify" << file.fileName(); } } else { qDebug() << "Can't find" << file.absolutePath(); } - return PackedResourceType::UNKNOWN; -} - -QString getPackedTypeName(PackedResourceType type) -{ - return s_packed_type_names.constFind(type).value(); + return ModPlatform::ResourceType::Unknown; } } // namespace ResourceUtils diff --git a/launcher/minecraft/mod/tasks/LocalResourceParse.h b/launcher/minecraft/mod/tasks/LocalResourceParse.h index 7385d24b0..dc3aeb025 100644 --- a/launcher/minecraft/mod/tasks/LocalResourceParse.h +++ b/launcher/minecraft/mod/tasks/LocalResourceParse.h @@ -21,17 +21,9 @@ #pragma once -#include - -#include #include -#include +#include "modplatform/ResourceType.h" -enum class PackedResourceType { DataPack, ResourcePack, TexturePack, ShaderPack, WorldSave, Mod, UNKNOWN }; namespace ResourceUtils { -static const std::set ValidResourceTypes = { PackedResourceType::DataPack, PackedResourceType::ResourcePack, - PackedResourceType::TexturePack, PackedResourceType::ShaderPack, - PackedResourceType::WorldSave, PackedResourceType::Mod }; -PackedResourceType identify(QFileInfo file); -QString getPackedTypeName(PackedResourceType type); +ModPlatform::ResourceType identify(QFileInfo file); } // namespace ResourceUtils diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index cfe4eba75..6a316af9f 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -43,8 +43,6 @@ QList modLoaderTypesToList(ModLoaderTypes flags); enum class ResourceProvider { MODRINTH, FLAME }; -enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK, MODPACK, DATA_PACK }; - enum class DependencyType { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE, UNKNOWN }; enum class Side { NoSide = 0, ClientSide = 1 << 0, ServerSide = 1 << 1, UniversalSide = ClientSide | ServerSide }; diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index bd6b90227..0799d1450 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -48,6 +48,7 @@ #include "../Version.h" #include "modplatform/ModIndex.h" +#include "modplatform/ResourceType.h" #include "tasks/Task.h" /* Simple class with a common interface for interacting with APIs */ diff --git a/launcher/modplatform/ResourceType.cpp b/launcher/modplatform/ResourceType.cpp new file mode 100644 index 000000000..2758f113f --- /dev/null +++ b/launcher/modplatform/ResourceType.cpp @@ -0,0 +1,41 @@ +// SPDX-FileCopyrightText: 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ResourceType.h" + +namespace ModPlatform { +static const QMap s_packedTypeNames = { { ResourceType::ResourcePack, QObject::tr("resource pack") }, + { ResourceType::TexturePack, QObject::tr("texture pack") }, + { ResourceType::DataPack, QObject::tr("data pack") }, + { ResourceType::ShaderPack, QObject::tr("shader pack") }, + { ResourceType::World, QObject::tr("world save") }, + { ResourceType::Mod, QObject::tr("mod") }, + { ResourceType::Unknown, QObject::tr("unknown") } }; + +namespace ResourceTypeUtils { + +QString getName(ResourceType type) +{ + return s_packedTypeNames.constFind(type).value(); +} + +} // namespace ResourceTypeUtils +} // namespace ModPlatform diff --git a/launcher/modplatform/ResourceType.h b/launcher/modplatform/ResourceType.h new file mode 100644 index 000000000..4acc384d1 --- /dev/null +++ b/launcher/modplatform/ResourceType.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include +#include +#include + +namespace ModPlatform { + +enum class ResourceType { Mod, ResourcePack, ShaderPack, Modpack, DataPack, World, Screenshots, TexturePack, Unknown }; + +namespace ResourceTypeUtils { +static const std::set ValidResources = { ResourceType::DataPack, ResourceType::ResourcePack, ResourceType::TexturePack, + ResourceType::ShaderPack, ResourceType::World, ResourceType::Mod }; +QString getName(ResourceType type); +} // namespace ResourceTypeUtils +} // namespace ModPlatform \ No newline at end of file diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 5f812d219..6dacb43de 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -84,18 +84,18 @@ void Flame::FileResolvingTask::executeTask() m_task->start(); } -PackedResourceType getResourceType(int classId) +ModPlatform::ResourceType getResourceType(int classId) { switch (classId) { case 17: // Worlds - return PackedResourceType::WorldSave; + return ModPlatform::ResourceType::World; case 6: // Mods - return PackedResourceType::Mod; + return ModPlatform::ResourceType::Mod; case 12: // Resource Packs - // return PackedResourceType::ResourcePack; // not really a resourcepack + // return ModPlatform::ResourceType::ResourcePack; // not really a resourcepack /* fallthrough */ case 4546: // Customization - // return PackedResourceType::ShaderPack; // not really a shaderPack + // return ModPlatform::ResourceType::ShaderPack; // not really a shaderPack /* fallthrough */ case 4471: // Modpacks /* fallthrough */ @@ -104,7 +104,7 @@ PackedResourceType getResourceType(int classId) case 4559: // Addons /* fallthrough */ default: - return PackedResourceType::UNKNOWN; + return ModPlatform::ResourceType::Unknown; } } @@ -256,7 +256,7 @@ void Flame::FileResolvingTask::getFlameProjects() setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(file->version.fileName)); FlameMod::loadIndexedPack(file->pack, entry_obj); file->resourceType = getResourceType(Json::requireInteger(entry_obj, "classId", "modClassId")); - if (file->resourceType == PackedResourceType::WorldSave) { + if (file->resourceType == ModPlatform::ResourceType::World) { file->targetFolder = "saves"; } } diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 0a5997ed9..d1facfd23 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -182,7 +182,7 @@ Task::Ptr FlameAPI::getCategories(std::shared_ptr response, ModPlatf Task::Ptr FlameAPI::getModCategories(std::shared_ptr response) { - return getCategories(response, ModPlatform::ResourceType::MOD); + return getCategories(response, ModPlatform::ResourceType::Mod); } QList FlameAPI::loadModCategories(std::shared_ptr response) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 316d2e9c9..88b108910 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -41,15 +41,15 @@ class FlameAPI : public NetworkResourceAPI { { switch (type) { default: - case ModPlatform::ResourceType::MOD: + case ModPlatform::ResourceType::Mod: return 6; - case ModPlatform::ResourceType::RESOURCE_PACK: + case ModPlatform::ResourceType::ResourcePack: return 12; - case ModPlatform::ResourceType::SHADER_PACK: + case ModPlatform::ResourceType::ShaderPack: return 6552; - case ModPlatform::ResourceType::MODPACK: + case ModPlatform::ResourceType::Modpack: return 4471; - case ModPlatform::ResourceType::DATA_PACK: + case ModPlatform::ResourceType::DataPack: return 6945; } } diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index adf4c1065..caf75fe6c 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -517,7 +517,7 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) QList blocked_mods; auto anyBlocked = false; for (const auto& result : results.values()) { - if (result.resourceType != PackedResourceType::Mod) { + if (result.resourceType != ModPlatform::ResourceType::Mod) { m_otherResources.append(std::make_pair(result.version.fileName, result.targetFolder)); } @@ -687,29 +687,29 @@ void FlameCreationTask::validateOtherResources(QEventLoop& loop) QString worldPath; switch (type) { - case PackedResourceType::Mod: + case ModPlatform::ResourceType::Mod: validatePath(fileName, targetFolder, "mods"); zipMods.push_back(fileName); break; - case PackedResourceType::ResourcePack: + case ModPlatform::ResourceType::ResourcePack: validatePath(fileName, targetFolder, "resourcepacks"); break; - case PackedResourceType::TexturePack: + case ModPlatform::ResourceType::TexturePack: validatePath(fileName, targetFolder, "texturepacks"); break; - case PackedResourceType::DataPack: + case ModPlatform::ResourceType::DataPack: validatePath(fileName, targetFolder, "datapacks"); break; - case PackedResourceType::ShaderPack: + case ModPlatform::ResourceType::ShaderPack: // in theory flame API can't do this but who knows, that *may* change ? // better to handle it if it *does* occur in the future validatePath(fileName, targetFolder, "shaderpacks"); break; - case PackedResourceType::WorldSave: + case ModPlatform::ResourceType::World: worldPath = validatePath(fileName, targetFolder, "saves"); installWorld(worldPath); break; - case PackedResourceType::UNKNOWN: + case ModPlatform::ResourceType::Unknown: /* fallthrough */ default: qDebug() << "Can't Identify" << fileName << "at" << localPath << ", leaving it where it is."; diff --git a/launcher/modplatform/flame/PackManifest.h b/launcher/modplatform/flame/PackManifest.h index 6b911ffb4..049a99871 100644 --- a/launcher/modplatform/flame/PackManifest.h +++ b/launcher/modplatform/flame/PackManifest.h @@ -40,8 +40,8 @@ #include #include #include -#include "minecraft/mod/tasks/LocalResourceParse.h" #include "modplatform/ModIndex.h" +#include "modplatform/ResourceType.h" namespace Flame { struct File { @@ -55,7 +55,7 @@ struct File { // our QString targetFolder = QStringLiteral("mods"); - PackedResourceType resourceType; + ModPlatform::ResourceType resourceType; }; struct Modloader { diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 7c2592256..4fa70f425 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -104,15 +104,15 @@ class ModrinthAPI : public NetworkResourceAPI { [[nodiscard]] static QString resourceTypeParameter(ModPlatform::ResourceType type) { switch (type) { - case ModPlatform::ResourceType::MOD: + case ModPlatform::ResourceType::Mod: return "mod"; - case ModPlatform::ResourceType::RESOURCE_PACK: + case ModPlatform::ResourceType::ResourcePack: return "resourcepack"; - case ModPlatform::ResourceType::SHADER_PACK: + case ModPlatform::ResourceType::ShaderPack: return "shader"; - case ModPlatform::ResourceType::DATA_PACK: + case ModPlatform::ResourceType::DataPack: return "datapack"; - case ModPlatform::ResourceType::MODPACK: + case ModPlatform::ResourceType::Modpack: return "modpack"; default: qWarning() << "Invalid resource type for Modrinth API!"; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 9edbda605..3209f080f 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1041,7 +1041,7 @@ void MainWindow::processURLs(QList urls) auto type = ResourceUtils::identify(localFileInfo); - if (ResourceUtils::ValidResourceTypes.count(type) == 0) { // probably instance/modpack + if (ModPlatform::ResourceTypeUtils::ValidResources.count(type) == 0) { // probably instance/modpack addInstance(localFileName, extra_info); continue; } @@ -1065,25 +1065,25 @@ void MainWindow::processURLs(QList urls) auto minecraftInst = std::dynamic_pointer_cast(inst); switch (type) { - case PackedResourceType::ResourcePack: + case ModPlatform::ResourceType::ResourcePack: minecraftInst->resourcePackList()->installResourceWithFlameMetadata(localFileName, version); break; - case PackedResourceType::TexturePack: + case ModPlatform::ResourceType::TexturePack: minecraftInst->texturePackList()->installResourceWithFlameMetadata(localFileName, version); break; - case PackedResourceType::DataPack: + case ModPlatform::ResourceType::DataPack: qWarning() << "Importing of Data Packs not supported at this time. Ignoring" << localFileName; break; - case PackedResourceType::Mod: + case ModPlatform::ResourceType::Mod: minecraftInst->loaderModList()->installResourceWithFlameMetadata(localFileName, version); break; - case PackedResourceType::ShaderPack: + case ModPlatform::ResourceType::ShaderPack: minecraftInst->shaderPackList()->installResourceWithFlameMetadata(localFileName, version); break; - case PackedResourceType::WorldSave: + case ModPlatform::ResourceType::World: minecraftInst->worldList()->installWorld(localFileInfo); break; - case PackedResourceType::UNKNOWN: + case ModPlatform::ResourceType::Unknown: default: qDebug() << "Can't Identify" << localFileName << "Ignoring it."; break; diff --git a/launcher/ui/dialogs/ImportResourceDialog.cpp b/launcher/ui/dialogs/ImportResourceDialog.cpp index 97c8f22c5..7cd178130 100644 --- a/launcher/ui/dialogs/ImportResourceDialog.cpp +++ b/launcher/ui/dialogs/ImportResourceDialog.cpp @@ -8,10 +8,11 @@ #include "InstanceList.h" #include +#include "modplatform/ResourceType.h" #include "ui/instanceview/InstanceDelegate.h" #include "ui/instanceview/InstanceProxyModel.h" -ImportResourceDialog::ImportResourceDialog(QString file_path, PackedResourceType type, QWidget* parent) +ImportResourceDialog::ImportResourceDialog(QString file_path, ModPlatform::ResourceType type, QWidget* parent) : QDialog(parent), ui(new Ui::ImportResourceDialog), m_resource_type(type), m_file_path(file_path) { ui->setupUi(this); @@ -42,7 +43,7 @@ ImportResourceDialog::ImportResourceDialog(QString file_path, PackedResourceType connect(contentsWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ImportResourceDialog::selectionChanged); ui->label->setText( - tr("Choose the instance you would like to import this %1 to.").arg(ResourceUtils::getPackedTypeName(m_resource_type))); + tr("Choose the instance you would like to import this %1 to.").arg(ModPlatform::ResourceTypeUtils::getName(m_resource_type))); ui->label_file_path->setText(tr("File: %1").arg(m_file_path)); ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); diff --git a/launcher/ui/dialogs/ImportResourceDialog.h b/launcher/ui/dialogs/ImportResourceDialog.h index bbde1ba7b..d96099661 100644 --- a/launcher/ui/dialogs/ImportResourceDialog.h +++ b/launcher/ui/dialogs/ImportResourceDialog.h @@ -3,7 +3,7 @@ #include #include -#include "minecraft/mod/tasks/LocalResourceParse.h" +#include "modplatform/ResourceType.h" #include "ui/instanceview/InstanceProxyModel.h" namespace Ui { @@ -14,13 +14,13 @@ class ImportResourceDialog : public QDialog { Q_OBJECT public: - explicit ImportResourceDialog(QString file_path, PackedResourceType type, QWidget* parent = nullptr); + explicit ImportResourceDialog(QString file_path, ModPlatform::ResourceType type, QWidget* parent = nullptr); ~ImportResourceDialog() override; QString selectedInstanceKey; private: Ui::ImportResourceDialog* ui; - PackedResourceType m_resource_type; + ModPlatform::ResourceType m_resource_type; QString m_file_path; InstanceProxyModel* proxyModel; diff --git a/launcher/ui/pages/modplatform/DataPackModel.cpp b/launcher/ui/pages/modplatform/DataPackModel.cpp index 085bd2d53..547f0a363 100644 --- a/launcher/ui/pages/modplatform/DataPackModel.cpp +++ b/launcher/ui/pages/modplatform/DataPackModel.cpp @@ -18,7 +18,7 @@ DataPackResourceModel::DataPackResourceModel(BaseInstance const& base_inst, Reso ResourceAPI::SearchArgs DataPackResourceModel::createSearchArguments() { auto sort = getCurrentSortingMethodByIndex(); - return { ModPlatform::ResourceType::DATA_PACK, m_next_search_offset, m_search_term, sort, ModPlatform::ModLoaderType::DataPack }; + return { ModPlatform::ResourceType::DataPack, m_next_search_offset, m_search_term, sort, ModPlatform::ModLoaderType::DataPack }; } ResourceAPI::VersionSearchArgs DataPackResourceModel::createVersionsArguments(const QModelIndex& entry) diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 32e6f2146..feaa4cfa7 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -41,7 +41,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments() auto sort = getCurrentSortingMethodByIndex(); return { - ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, loaders, versions, side, categories, m_filter->openSource + ModPlatform::ResourceType::Mod, m_next_search_offset, m_search_term, sort, loaders, versions, side, categories, m_filter->openSource }; } diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.cpp b/launcher/ui/pages/modplatform/ResourcePackModel.cpp index 0de980ed8..986cb56a6 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.cpp +++ b/launcher/ui/pages/modplatform/ResourcePackModel.cpp @@ -17,7 +17,7 @@ ResourcePackResourceModel::ResourcePackResourceModel(BaseInstance const& base_in ResourceAPI::SearchArgs ResourcePackResourceModel::createSearchArguments() { auto sort = getCurrentSortingMethodByIndex(); - return { ModPlatform::ResourceType::RESOURCE_PACK, m_next_search_offset, m_search_term, sort }; + return { ModPlatform::ResourceType::ResourcePack, m_next_search_offset, m_search_term, sort }; } ResourceAPI::VersionSearchArgs ResourcePackResourceModel::createVersionsArguments(const QModelIndex& entry) diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.cpp b/launcher/ui/pages/modplatform/ShaderPackModel.cpp index efc6bfaf9..b59bf182b 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackModel.cpp @@ -17,7 +17,7 @@ ShaderPackResourceModel::ShaderPackResourceModel(BaseInstance const& base_inst, ResourceAPI::SearchArgs ShaderPackResourceModel::createSearchArguments() { auto sort = getCurrentSortingMethodByIndex(); - return { ModPlatform::ResourceType::SHADER_PACK, m_next_search_offset, m_search_term, sort }; + return { ModPlatform::ResourceType::ShaderPack, m_next_search_offset, m_search_term, sort }; } ResourceAPI::VersionSearchArgs ShaderPackResourceModel::createVersionsArguments(const QModelIndex& entry) diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index e67e4fb38..f8fca6570 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -188,7 +188,7 @@ void ListModel::performPaginatedSearch() auto netJob = makeShared("Flame::Search", APPLICATION->network()); auto searchUrl = - FlameAPI().getSearchURL({ ModPlatform::ResourceType::MODPACK, nextSearchOffset, currentSearchTerm, sort, m_filter->loaders, + FlameAPI().getSearchURL({ ModPlatform::ResourceType::Modpack, nextSearchOffset, currentSearchTerm, sort, m_filter->loaders, m_filter->versions, ModPlatform::Side::NoSide, m_filter->categoryIds, m_filter->openSource }); netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl.value()), response)); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 1a2fc7aa4..9578eb73e 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -350,7 +350,7 @@ void FlamePage::createFilterWidget() connect(m_filterWidget.get(), &ModFilterWidget::filterChanged, this, &FlamePage::triggerSearch); auto response = std::make_shared(); - m_categoriesTask = FlameAPI::getCategories(response, ModPlatform::ResourceType::MODPACK); + m_categoriesTask = FlameAPI::getCategories(response, ModPlatform::ResourceType::Modpack); connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { auto categories = FlameAPI::loadModCategories(response); m_filterWidget->setCategories(categories); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 870b47beb..c66fb5655 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -154,7 +154,7 @@ void ModpackListModel::performPaginatedSearch() ResourceAPI::SortingMethod sort{}; sort.name = currentSort; auto searchUrl = - ModrinthAPI().getSearchURL({ ModPlatform::ResourceType::MODPACK, nextSearchOffset, currentSearchTerm, sort, m_filter->loaders, + ModrinthAPI().getSearchURL({ ModPlatform::ResourceType::Modpack, nextSearchOffset, currentSearchTerm, sort, m_filter->loaders, m_filter->versions, ModPlatform::Side::NoSide, m_filter->categoryIds, m_filter->openSource }); auto netJob = makeShared("Modrinth::SearchModpack", APPLICATION->network()); From 6f23c6ea416868684717c8c98e97ee36751909c0 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Fri, 18 Jul 2025 18:22:46 +0300 Subject: [PATCH 065/118] Update launcher/modplatform/ResourceType.h Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/modplatform/ResourceType.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/ResourceType.h b/launcher/modplatform/ResourceType.h index 4acc384d1..b9073aa17 100644 --- a/launcher/modplatform/ResourceType.h +++ b/launcher/modplatform/ResourceType.h @@ -32,7 +32,7 @@ namespace ModPlatform { enum class ResourceType { Mod, ResourcePack, ShaderPack, Modpack, DataPack, World, Screenshots, TexturePack, Unknown }; namespace ResourceTypeUtils { -static const std::set ValidResources = { ResourceType::DataPack, ResourceType::ResourcePack, ResourceType::TexturePack, +static const std::set VALID_RESOURCES = { ResourceType::DataPack, ResourceType::ResourcePack, ResourceType::TexturePack, ResourceType::ShaderPack, ResourceType::World, ResourceType::Mod }; QString getName(ResourceType type); } // namespace ResourceTypeUtils From b60b577d25008af0284834a420e0133b1eb17c7f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Jul 2025 18:26:25 +0300 Subject: [PATCH 066/118] rename VALID_RESOURCES static variable Signed-off-by: Trial97 --- launcher/ui/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 3209f080f..d89224504 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1041,7 +1041,7 @@ void MainWindow::processURLs(QList urls) auto type = ResourceUtils::identify(localFileInfo); - if (ModPlatform::ResourceTypeUtils::ValidResources.count(type) == 0) { // probably instance/modpack + if (ModPlatform::ResourceTypeUtils::VALID_RESOURCES.count(type) == 0) { // probably instance/modpack addInstance(localFileName, extra_info); continue; } From 43b2b07e0ec55cc0f8d2d6175ac467c3042adf86 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 20 Jul 2025 00:32:26 +0000 Subject: [PATCH 067/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/9807714d6944a957c2e036f84b0ff8caf9930bc0?narHash=sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X%2BxgOL0%3D' (2025-07-08) → 'github:NixOS/nixpkgs/6e987485eb2c77e5dcc5af4e3c70843711ef9251?narHash=sha256-RKwfXA4OZROjBTQAl9WOZQFm7L8Bo93FQwSJpAiSRvo%3D' (2025-07-16) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index b5f6258e1..162ad5baa 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1751984180, - "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=", + "lastModified": 1752687322, + "narHash": "sha256-RKwfXA4OZROjBTQAl9WOZQFm7L8Bo93FQwSJpAiSRvo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0", + "rev": "6e987485eb2c77e5dcc5af4e3c70843711ef9251", "type": "github" }, "original": { From a75713897d96c674fc1fc9b2d0ac751bf0a6bfbe Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 19 Dec 2024 11:18:22 +0200 Subject: [PATCH 068/118] chore:renamed variables to camelCase Signed-off-by: Trial97 --- launcher/modplatform/CheckUpdateTask.h | 14 ++-- .../modplatform/flame/FlameCheckUpdate.cpp | 10 +-- .../modrinth/ModrinthCheckUpdate.cpp | 20 ++--- .../modrinth/ModrinthCheckUpdate.h | 6 +- launcher/ui/dialogs/ResourceUpdateDialog.cpp | 80 +++++++++---------- launcher/ui/dialogs/ResourceUpdateDialog.h | 32 ++++---- 6 files changed, 80 insertions(+), 82 deletions(-) diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index 1ee820a63..c5beff26c 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -1,9 +1,7 @@ #pragma once -#include "minecraft/mod/Mod.h" #include "minecraft/mod/tasks/GetModDependenciesTask.h" #include "modplatform/ModIndex.h" -#include "modplatform/ResourceAPI.h" #include "tasks/Task.h" class ResourceDownloadTask; @@ -19,9 +17,9 @@ class CheckUpdateTask : public Task { std::shared_ptr resourceModel) : Task() , m_resources(resources) - , m_game_versions(mcVersions) - , m_loaders_list(std::move(loadersList)) - , m_resource_model(std::move(resourceModel)) + , m_gameVersions(mcVersions) + , m_loadersList(std::move(loadersList)) + , m_resourceModel(std::move(resourceModel)) {} struct Update { @@ -71,9 +69,9 @@ class CheckUpdateTask : public Task { protected: QList& m_resources; - std::list& m_game_versions; - QList m_loaders_list; - std::shared_ptr m_resource_model; + std::list& m_gameVersions; + QList m_loadersList; + std::shared_ptr m_resourceModel; std::vector m_updates; QList> m_deps; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index 047813675..8f54ee0c6 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -46,12 +46,12 @@ void FlameCheckUpdate::executeTask() connect(netJob, &Task::stepProgress, this, &FlameCheckUpdate::propagateStepProgress); connect(netJob, &Task::details, this, &FlameCheckUpdate::setDetails); for (auto* resource : m_resources) { - auto versions_url_optional = api.getVersionsURL({ { resource->metadata()->project_id.toString() }, m_game_versions }); - if (!versions_url_optional.has_value()) + auto versionsUrlOptional = api.getVersionsURL({ { resource->metadata()->project_id.toString() }, m_gameVersions }); + if (!versionsUrlOptional.has_value()) continue; auto response = std::make_shared(); - auto task = Net::ApiDownload::makeByteArray(versions_url_optional.value(), response); + auto task = Net::ApiDownload::makeByteArray(versionsUrlOptional.value(), response); connect(task.get(), &Task::succeeded, this, [this, resource, response] { getLatestVersionCallback(resource, response); }); netJob->addNetAction(task); @@ -87,7 +87,7 @@ void FlameCheckUpdate::getLatestVersionCallback(Resource* resource, std::shared_ qCritical() << e.what(); qDebug() << doc; } - auto latest_ver = api.getLatestVersion(pack->versions, m_loaders_list, resource->metadata()->loaders); + auto latest_ver = api.getLatestVersion(pack->versions, m_loadersList, resource->metadata()->loaders); setStatus(tr("Parsing the API response from CurseForge for '%1'...").arg(resource->name())); @@ -119,7 +119,7 @@ void FlameCheckUpdate::getLatestVersionCallback(Resource* resource, std::shared_ old_version = tr("Unknown"); } - auto download_task = makeShared(pack, latest_ver.value(), m_resource_model); + auto download_task = makeShared(pack, latest_ver.value(), m_resourceModel); m_updates.emplace_back(pack->name, resource->metadata()->hash, old_version, latest_ver->version, latest_ver->version_type, api.getModFileChangelog(latest_ver->addonId.toInt(), latest_ver->fileId.toInt()), ModPlatform::ResourceProvider::FLAME, download_task, resource->enabled()); diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index aa371f280..041ffddb7 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -30,7 +30,7 @@ bool ModrinthCheckUpdate::abort() void ModrinthCheckUpdate::executeTask() { setStatus(tr("Preparing resources for Modrinth...")); - setProgress(0, (m_loaders_list.isEmpty() ? 1 : m_loaders_list.length()) * 2 + 1); + setProgress(0, (m_loadersList.isEmpty() ? 1 : m_loadersList.length()) * 2 + 1); auto hashing_task = makeShared("MakeModrinthHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); @@ -40,7 +40,7 @@ void ModrinthCheckUpdate::executeTask() // Sadly the API can only handle one hash type per call, se we // need to generate a new hash if the current one is innadequate // (though it will rarely happen, if at all) - if (resource->metadata()->hash_format != m_hash_type) { + if (resource->metadata()->hash_format != m_hashType) { auto hash_task = Hashing::createHasher(resource->fileinfo().absoluteFilePath(), ModPlatform::ResourceProvider::MODRINTH); connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, resource](QString hash) { m_mappings.insert(hash, resource); }); connect(hash_task.get(), &Task::failed, [this] { failed("Failed to generate hash"); }); @@ -62,7 +62,7 @@ void ModrinthCheckUpdate::getUpdateModsForLoader(std::optional(); QStringList hashes = m_mappings.keys(); - auto job = api.latestVersions(hashes, m_hash_type, m_game_versions, loader, response); + auto job = api.latestVersions(hashes, m_hashType, m_gameVersions, loader, response); connect(job.get(), &Task::succeeded, this, [this, response, loader] { checkVersionsResponse(response, loader); }); @@ -121,7 +121,7 @@ void ModrinthCheckUpdate::checkVersionsResponse(std::shared_ptr resp // - The version reported by the JAR is different from the version reported by the indexed version (it's usually the case) // Such is the pain of having arbitrary files for a given version .-. - auto project_ver = Modrinth::loadIndexedPackVersion(project_obj, m_hash_type, loader_filter); + auto project_ver = Modrinth::loadIndexedPackVersion(project_obj, m_hashType, loader_filter); if (project_ver.downloadUrl.isEmpty()) { qCritical() << "Modrinth mod without download url!" << project_ver.fileName; ++iter; @@ -135,7 +135,7 @@ void ModrinthCheckUpdate::checkVersionsResponse(std::shared_ptr resp pack->addonId = resource->metadata()->project_id; pack->provider = ModPlatform::ResourceProvider::MODRINTH; if ((project_ver.hash != hash && project_ver.is_preferred) || (resource->status() == ResourceStatus::NOT_INSTALLED)) { - auto download_task = makeShared(pack, project_ver, m_resource_model); + auto download_task = makeShared(pack, project_ver, m_resourceModel); QString old_version = resource->metadata()->version_number; if (old_version.isEmpty()) { @@ -166,15 +166,15 @@ void ModrinthCheckUpdate::checkNextLoader() return; } - if (m_loaders_list.isEmpty() && m_loader_idx == 0) { + if (m_loadersList.isEmpty() && m_loaderIdx == 0) { getUpdateModsForLoader({}); - m_loader_idx++; + m_loaderIdx++; return; } - if (m_loader_idx < m_loaders_list.size()) { - getUpdateModsForLoader(m_loaders_list.at(m_loader_idx)); - m_loader_idx++; + if (m_loaderIdx < m_loadersList.size()) { + getUpdateModsForLoader(m_loadersList.at(m_loaderIdx)); + m_loaderIdx++; return; } diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h index 204b24784..bde61bb23 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h @@ -11,7 +11,7 @@ class ModrinthCheckUpdate : public CheckUpdateTask { QList loadersList, std::shared_ptr resourceModel) : CheckUpdateTask(resources, mcVersions, std::move(loadersList), std::move(resourceModel)) - , m_hash_type(ModPlatform::ProviderCapabilities::hashType(ModPlatform::ResourceProvider::MODRINTH).first()) + , m_hashType(ModPlatform::ProviderCapabilities::hashType(ModPlatform::ResourceProvider::MODRINTH).first()) {} public slots: @@ -26,6 +26,6 @@ class ModrinthCheckUpdate : public CheckUpdateTask { private: Task::Ptr m_job = nullptr; QHash m_mappings; - QString m_hash_type; - int m_loader_idx = 0; + QString m_hashType; + int m_loaderIdx = 0; }; diff --git a/launcher/ui/dialogs/ResourceUpdateDialog.cpp b/launcher/ui/dialogs/ResourceUpdateDialog.cpp index 774d3a339..eb69a6c6b 100644 --- a/launcher/ui/dialogs/ResourceUpdateDialog.cpp +++ b/launcher/ui/dialogs/ResourceUpdateDialog.cpp @@ -34,17 +34,17 @@ static std::list mcVersions(BaseInstance* inst) ResourceUpdateDialog::ResourceUpdateDialog(QWidget* parent, BaseInstance* instance, - const std::shared_ptr resource_model, - QList& search_for, - bool include_deps, + const std::shared_ptr resourceModel, + QList& searchFor, + bool includeDeps, QList loadersList) : ReviewMessageBox(parent, tr("Confirm resources to update"), "") , m_parent(parent) - , m_resource_model(resource_model) - , m_candidates(search_for) - , m_second_try_metadata(new ConcurrentTask("Second Metadata Search", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())) + , m_resourceModel(resourceModel) + , m_candidates(searchFor) + , m_secondTryMetadata(new ConcurrentTask("Second Metadata Search", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())) , m_instance(instance) - , m_include_deps(include_deps) + , m_includeDeps(includeDeps) , m_loadersList(std::move(loadersList)) { ReviewMessageBox::setGeometry(0, 0, 800, 600); @@ -63,9 +63,9 @@ void ResourceUpdateDialog::checkCandidates() } // Report failed metadata generation - if (!m_failed_metadata.empty()) { + if (!m_failedMetadata.empty()) { QString text; - for (const auto& failed : m_failed_metadata) { + for (const auto& failed : m_failedMetadata) { const auto& mod = std::get<0>(failed); const auto& reason = std::get<1>(failed); text += tr("Mod name: %1
File name: %2
Reason: %3

").arg(mod->name(), mod->fileinfo().fileName(), reason); @@ -84,24 +84,24 @@ void ResourceUpdateDialog::checkCandidates() } auto versions = mcVersions(m_instance); + SequentialTask check_task(tr("Checking for updates")); - if (!m_modrinth_to_update.empty()) { - m_modrinth_check_task.reset(new ModrinthCheckUpdate(m_modrinth_to_update, versions, m_loadersList, m_resource_model)); - connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, + if (!m_modrinthToUpdate.empty()) { + m_modrinthCheckTask.reset(new ModrinthCheckUpdate(m_modrinthToUpdate, versions, m_loadersList, m_resourceModel)); + connect(m_modrinthCheckTask.get(), &CheckUpdateTask::checkFailed, this, [this](Resource* resource, QString reason, QUrl recover_url) { - m_failed_check_update.append({ resource, reason, recover_url }); + m_failedCheckUpdate.append({ resource, reason, recover_url }); }); - check_task.addTask(m_modrinth_check_task); + check_task.addTask(m_modrinthCheckTask); } - if (!m_flame_to_update.empty()) { - m_flame_check_task.reset(new FlameCheckUpdate(m_flame_to_update, versions, m_loadersList, m_resource_model)); - connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, - [this](Resource* resource, QString reason, QUrl recover_url) { - m_failed_check_update.append({ resource, reason, recover_url }); - }); - check_task.addTask(m_flame_check_task); + if (!m_flameToUpdate.empty()) { + m_flameCheckTask.reset(new FlameCheckUpdate(m_flameToUpdate, versions, m_loadersList, m_resourceModel)); + connect(m_flameCheckTask.get(), &CheckUpdateTask::checkFailed, this, [this](Resource* resource, QString reason, QUrl recover_url) { + m_failedCheckUpdate.append({ resource, reason, recover_url }); + }); + check_task.addTask(m_flameCheckTask); } connect(&check_task, &Task::failed, this, @@ -130,33 +130,33 @@ void ResourceUpdateDialog::checkCandidates() QList> selectedVers; // Add found updates for Modrinth - if (m_modrinth_check_task) { - auto modrinth_updates = m_modrinth_check_task->getUpdates(); + if (m_modrinthCheckTask) { + auto modrinth_updates = m_modrinthCheckTask->getUpdates(); for (auto& updatable : modrinth_updates) { qDebug() << QString("Mod %1 has an update available!").arg(updatable.name); appendResource(updatable); m_tasks.insert(updatable.name, updatable.download); } - selectedVers.append(m_modrinth_check_task->getDependencies()); + selectedVers.append(m_modrinthCheckTask->getDependencies()); } // Add found updated for Flame - if (m_flame_check_task) { - auto flame_updates = m_flame_check_task->getUpdates(); + if (m_flameCheckTask) { + auto flame_updates = m_flameCheckTask->getUpdates(); for (auto& updatable : flame_updates) { qDebug() << QString("Mod %1 has an update available!").arg(updatable.name); appendResource(updatable); m_tasks.insert(updatable.name, updatable.download); } - selectedVers.append(m_flame_check_task->getDependencies()); + selectedVers.append(m_flameCheckTask->getDependencies()); } // Report failed update checking - if (!m_failed_check_update.empty()) { + if (!m_failedCheckUpdate.empty()) { QString text; - for (const auto& failed : m_failed_check_update) { + for (const auto& failed : m_failedCheckUpdate) { const auto& mod = std::get<0>(failed); const auto& reason = std::get<1>(failed); const auto& recover_url = std::get<2>(failed); @@ -185,8 +185,8 @@ void ResourceUpdateDialog::checkCandidates() } } - if (m_include_deps && !APPLICATION->settings()->get("ModDependenciesDisabled").toBool()) { // dependencies - auto* mod_model = dynamic_cast(m_resource_model.get()); + if (m_includeDeps && !APPLICATION->settings()->get("ModDependenciesDisabled").toBool()) { // dependencies + auto* mod_model = dynamic_cast(m_resourceModel.get()); if (mod_model != nullptr) { auto depTask = makeShared(m_instance, mod_model, selectedVers); @@ -224,7 +224,7 @@ void ResourceUpdateDialog::checkCandidates() auto changelog = dep->version.changelog; if (dep->pack->provider == ModPlatform::ResourceProvider::FLAME) changelog = api.getModFileChangelog(dep->version.addonId.toInt(), dep->version.fileId.toInt()); - auto download_task = makeShared(dep->pack, dep->version, m_resource_model); + auto download_task = makeShared(dep->pack, dep->version, m_resourceModel); auto extraInfo = dependencyExtraInfo.value(dep->version.addonId.toString()); CheckUpdateTask::Update updatable = { dep->pack->name, dep->version.hash, tr("Not installed"), dep->version.version, dep->version.version_type, @@ -239,7 +239,7 @@ void ResourceUpdateDialog::checkCandidates() // If there's no resource to be updated if (ui->modTreeWidget->topLevelItemCount() == 0) { - m_no_updates = true; + m_noUpdates = true; } else { // FIXME: Find a more efficient way of doing this! @@ -254,7 +254,7 @@ void ResourceUpdateDialog::checkCandidates() } } - if (m_aborted || m_no_updates) + if (m_aborted || m_noUpdates) QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); } @@ -362,7 +362,7 @@ auto ResourceUpdateDialog::ensureMetadata() -> bool seq.addTask(flame_task); } - seq.addTask(m_second_try_metadata); + seq.addTask(m_secondTryMetadata); // execute all the tasks ProgressDialog checking_dialog(m_parent); @@ -381,10 +381,10 @@ void ResourceUpdateDialog::onMetadataEnsured(Resource* resource) switch (resource->metadata()->provider) { case ModPlatform::ResourceProvider::MODRINTH: - m_modrinth_to_update.push_back(resource); + m_modrinthToUpdate.push_back(resource); break; case ModPlatform::ResourceProvider::FLAME: - m_flame_to_update.push_back(resource); + m_flameToUpdate.push_back(resource); break; } } @@ -415,14 +415,14 @@ void ResourceUpdateDialog::onMetadataFailed(Resource* resource, bool try_others, auto seq = makeShared(); seq->addTask(task->getHashingTask()); seq->addTask(task); - m_second_try_metadata->addTask(seq); + m_secondTryMetadata->addTask(seq); } else { - m_second_try_metadata->addTask(task); + m_secondTryMetadata->addTask(task); } } else { QString reason{ tr("Couldn't find a valid version on the selected mod provider(s)") }; - m_failed_metadata.append({ resource, reason }); + m_failedMetadata.append({ resource, reason }); } } diff --git a/launcher/ui/dialogs/ResourceUpdateDialog.h b/launcher/ui/dialogs/ResourceUpdateDialog.h index aef11c90f..be3c19dcc 100644 --- a/launcher/ui/dialogs/ResourceUpdateDialog.h +++ b/launcher/ui/dialogs/ResourceUpdateDialog.h @@ -18,9 +18,9 @@ class ResourceUpdateDialog final : public ReviewMessageBox { public: explicit ResourceUpdateDialog(QWidget* parent, BaseInstance* instance, - std::shared_ptr resource_model, - QList& search_for, - bool include_deps, + std::shared_ptr resourceModel, + QList& searchFor, + bool includeDeps, QList loadersList = {}); void checkCandidates(); @@ -28,9 +28,9 @@ class ResourceUpdateDialog final : public ReviewMessageBox { void appendResource(const CheckUpdateTask::Update& info, QStringList requiredBy = {}); const QList getTasks(); - auto indexDir() const -> QDir { return m_resource_model->indexDir(); } + auto indexDir() const -> QDir { return m_resourceModel->indexDir(); } - auto noUpdates() const -> bool { return m_no_updates; }; + auto noUpdates() const -> bool { return m_noUpdates; }; auto aborted() const -> bool { return m_aborted; }; private: @@ -40,29 +40,29 @@ class ResourceUpdateDialog final : public ReviewMessageBox { void onMetadataEnsured(Resource* resource); void onMetadataFailed(Resource* resource, bool try_others = false, - ModPlatform::ResourceProvider first_choice = ModPlatform::ResourceProvider::MODRINTH); + ModPlatform::ResourceProvider firstChoice = ModPlatform::ResourceProvider::MODRINTH); private: QWidget* m_parent; - shared_qobject_ptr m_modrinth_check_task; - shared_qobject_ptr m_flame_check_task; + shared_qobject_ptr m_modrinthCheckTask; + shared_qobject_ptr m_flameCheckTask; - const std::shared_ptr m_resource_model; + const std::shared_ptr m_resourceModel; QList& m_candidates; - QList m_modrinth_to_update; - QList m_flame_to_update; + QList m_modrinthToUpdate; + QList m_flameToUpdate; - ConcurrentTask::Ptr m_second_try_metadata; - QList> m_failed_metadata; - QList> m_failed_check_update; + ConcurrentTask::Ptr m_secondTryMetadata; + QList> m_failedMetadata; + QList> m_failedCheckUpdate; QHash m_tasks; BaseInstance* m_instance; - bool m_no_updates = false; + bool m_noUpdates = false; bool m_aborted = false; - bool m_include_deps = false; + bool m_includeDeps = false; QList m_loadersList; }; From bd570aa5d1d371675ecedcf8df1437bf155853e7 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 16 Nov 2024 00:54:36 +0200 Subject: [PATCH 069/118] fix:resource update with loaders Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.cpp | 12 +++- launcher/modplatform/flame/FlameAPI.h | 3 +- .../modplatform/flame/FlameCheckUpdate.cpp | 2 +- .../modrinth/ModrinthCheckUpdate.cpp | 61 ++++++++++++++----- .../modrinth/ModrinthCheckUpdate.h | 8 +-- 5 files changed, 63 insertions(+), 23 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index d1facfd23..b0d9af804 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -218,9 +218,19 @@ QList FlameAPI::loadModCategories(std::shared_ptr FlameAPI::getLatestVersion(QList versions, QList instanceLoaders, - ModPlatform::ModLoaderTypes modLoaders) + ModPlatform::ModLoaderTypes modLoaders, + bool checkLoaders) { static const auto noLoader = ModPlatform::ModLoaderType(0); + if (!checkLoaders) { + std::optional ver; + for (auto file_tmp : versions) { + if (!ver.has_value() || file_tmp.date > ver->date) { + ver = file_tmp; + } + } + return ver; + } QHash bestMatch; auto checkVersion = [&bestMatch](const ModPlatform::IndexedVersion& version, const ModPlatform::ModLoaderType& loader) { if (bestMatch.contains(loader)) { diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index f72bdb624..5b8f794e6 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -18,7 +18,8 @@ class FlameAPI : public NetworkResourceAPI { std::optional getLatestVersion(QList versions, QList instanceLoaders, - ModPlatform::ModLoaderTypes fallback); + ModPlatform::ModLoaderTypes fallback, + bool checkLoaders); Task::Ptr getProjects(QStringList addonIds, std::shared_ptr response) const override; Task::Ptr matchFingerprints(const QList& fingerprints, std::shared_ptr response); diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index 8f54ee0c6..17d13deda 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -87,7 +87,7 @@ void FlameCheckUpdate::getLatestVersionCallback(Resource* resource, std::shared_ qCritical() << e.what(); qDebug() << doc; } - auto latest_ver = api.getLatestVersion(pack->versions, m_loadersList, resource->metadata()->loaders); + auto latest_ver = api.getLatestVersion(pack->versions, m_loadersList, resource->metadata()->loaders, !m_loadersList.isEmpty()); setStatus(tr("Parsing the API response from CurseForge for '%1'...").arg(resource->name())); diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 041ffddb7..6683a0ed5 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -15,6 +15,26 @@ static ModrinthAPI api; +ModrinthCheckUpdate::ModrinthCheckUpdate(QList& resources, + std::list& mcVersions, + QList loadersList, + std::shared_ptr resourceModel) + : CheckUpdateTask(resources, mcVersions, std::move(loadersList), std::move(resourceModel)) + , m_hashType(ModPlatform::ProviderCapabilities::hashType(ModPlatform::ResourceProvider::MODRINTH).first()) +{ + if (!m_loadersList.isEmpty()) { // this is for mods so append all the other posible loaders to the initial list + m_initialSize = m_loadersList.length(); + ModPlatform::ModLoaderTypes modLoaders; + for (auto m : resources) { + modLoaders |= m->metadata()->loaders; + } + for (auto l : m_loadersList) { + modLoaders &= ~l; + } + m_loadersList.append(ModPlatform::modLoaderTypesToList(modLoaders)); + } +} + bool ModrinthCheckUpdate::abort() { if (m_job) @@ -34,6 +54,7 @@ void ModrinthCheckUpdate::executeTask() auto hashing_task = makeShared("MakeModrinthHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); + bool startHasing = false; for (auto* resource : m_resources) { auto hash = resource->metadata()->hash; @@ -45,23 +66,37 @@ void ModrinthCheckUpdate::executeTask() connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, resource](QString hash) { m_mappings.insert(hash, resource); }); connect(hash_task.get(), &Task::failed, [this] { failed("Failed to generate hash"); }); hashing_task->addTask(hash_task); + startHasing = true; } else { m_mappings.insert(hash, resource); } } - connect(hashing_task.get(), &Task::finished, this, &ModrinthCheckUpdate::checkNextLoader); - m_job = hashing_task; - hashing_task->start(); + if (startHasing) { + connect(hashing_task.get(), &Task::finished, this, &ModrinthCheckUpdate::checkNextLoader); + m_job = hashing_task; + hashing_task->start(); + } else { + checkNextLoader(); + } } -void ModrinthCheckUpdate::getUpdateModsForLoader(std::optional loader) +void ModrinthCheckUpdate::getUpdateModsForLoader(std::optional loader, bool forceModLoaderCheck) { setStatus(tr("Waiting for the API response from Modrinth...")); setProgress(m_progress + 1, m_progressTotal); auto response = std::make_shared(); - QStringList hashes = m_mappings.keys(); + QStringList hashes; + if (forceModLoaderCheck && loader.has_value()) { + for (auto hash : m_mappings.keys()) { + if (m_mappings[hash]->metadata()->loaders & loader.value()) { + hashes.append(hash); + } + } + } else { + hashes = m_mappings.keys(); + } auto job = api.latestVersions(hashes, m_hashType, m_gameVersions, loader, response); connect(job.get(), &Task::succeeded, this, [this, response, loader] { checkVersionsResponse(response, loader); }); @@ -69,6 +104,7 @@ void ModrinthCheckUpdate::getUpdateModsForLoader(std::optionalstart(); } @@ -165,16 +201,11 @@ void ModrinthCheckUpdate::checkNextLoader() emitSucceeded(); return; } - - if (m_loadersList.isEmpty() && m_loaderIdx == 0) { - getUpdateModsForLoader({}); - m_loaderIdx++; + if (m_loaderIdx < m_loadersList.size()) { // this are mods so check with loades + getUpdateModsForLoader(m_loadersList.at(m_loaderIdx), m_loaderIdx > m_initialSize); return; - } - - if (m_loaderIdx < m_loadersList.size()) { - getUpdateModsForLoader(m_loadersList.at(m_loaderIdx)); - m_loaderIdx++; + } else if (m_loadersList.isEmpty() && m_loaderIdx == 0) { // this are other resources no need to check more than once with empty loader + getUpdateModsForLoader(); return; } @@ -192,4 +223,4 @@ void ModrinthCheckUpdate::checkNextLoader() } emitSucceeded(); -} +} \ No newline at end of file diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h index bde61bb23..eb8057694 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h @@ -9,17 +9,14 @@ class ModrinthCheckUpdate : public CheckUpdateTask { ModrinthCheckUpdate(QList& resources, std::list& mcVersions, QList loadersList, - std::shared_ptr resourceModel) - : CheckUpdateTask(resources, mcVersions, std::move(loadersList), std::move(resourceModel)) - , m_hashType(ModPlatform::ProviderCapabilities::hashType(ModPlatform::ResourceProvider::MODRINTH).first()) - {} + std::shared_ptr resourceModel); public slots: bool abort() override; protected slots: void executeTask() override; - void getUpdateModsForLoader(std::optional loader); + void getUpdateModsForLoader(std::optional loader = {}, bool forceModLoaderCheck = false); void checkVersionsResponse(std::shared_ptr response, std::optional loader); void checkNextLoader(); @@ -28,4 +25,5 @@ class ModrinthCheckUpdate : public CheckUpdateTask { QHash m_mappings; QString m_hashType; int m_loaderIdx = 0; + int m_initialSize = 0; }; From 0ae0996adc7b50566965be68363a9a3fb8a19987 Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Sun, 13 Jul 2025 16:28:56 -0400 Subject: [PATCH 070/118] build(vcpkg): patch meson to support universal binaries tomlplusplus uses Meson as a build system, which makes us come across a small bug when building Universal Binaries with our custom triplet I hate vendoring this Signed-off-by: Seth Flynn --- COPYING.md | 23 + cmake/vcpkg-ports/vcpkg-tool-meson/README.md | 3 + .../vcpkg-tool-meson/adjust-args.patch | 13 + .../vcpkg-tool-meson/adjust-python-dep.patch | 45 ++ .../fix-libcpp-enable-assertions.patch | 52 ++ .../vcpkg-tool-meson/install.cmake | 5 + .../vcpkg-tool-meson/meson-intl.patch | 13 + .../vcpkg-tool-meson/meson.template.in | 43 ++ .../vcpkg-tool-meson/portfile.cmake | 45 ++ ...remove-freebsd-pcfile-specialization.patch | 23 + .../vcpkg-tool-meson/universal-osx.patch | 16 + .../vcpkg-tool-meson/vcpkg-port-config.cmake | 62 +++ cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg.json | 11 + .../vcpkg_configure_meson.cmake | 480 ++++++++++++++++++ .../vcpkg_install_meson.cmake | 71 +++ vcpkg-configuration.json | 3 + 16 files changed, 908 insertions(+) create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/README.md create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/adjust-args.patch create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/adjust-python-dep.patch create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/fix-libcpp-enable-assertions.patch create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/install.cmake create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/meson-intl.patch create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/meson.template.in create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/portfile.cmake create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/remove-freebsd-pcfile-specialization.patch create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/universal-osx.patch create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg-port-config.cmake create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg.json create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_configure_meson.cmake create mode 100644 cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_install_meson.cmake diff --git a/COPYING.md b/COPYING.md index f9b905351..e64bb8760 100644 --- a/COPYING.md +++ b/COPYING.md @@ -412,3 +412,26 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software. + +## vcpkg (`cmake/vcpkg-ports`) + + MIT License + + Copyright (c) Microsoft Corporation + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be included in all copies + or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/README.md b/cmake/vcpkg-ports/vcpkg-tool-meson/README.md new file mode 100644 index 000000000..9047c8037 --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/README.md @@ -0,0 +1,3 @@ +The only difference between this and the upstream vcpkg port is the addition of `universal-osx.patch`. It's very annoying we need to bundle this entire tree to do that. + +-@getchoo diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-args.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-args.patch new file mode 100644 index 000000000..ad800aa66 --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-args.patch @@ -0,0 +1,13 @@ +diff --git a/mesonbuild/cmake/toolchain.py b/mesonbuild/cmake/toolchain.py +index 11a00be5d..89ae490ff 100644 +--- a/mesonbuild/cmake/toolchain.py ++++ b/mesonbuild/cmake/toolchain.py +@@ -202,7 +202,7 @@ class CMakeToolchain: + @staticmethod + def is_cmdline_option(compiler: 'Compiler', arg: str) -> bool: + if compiler.get_argument_syntax() == 'msvc': +- return arg.startswith('/') ++ return arg.startswith(('/','-')) + else: + if os.path.basename(compiler.get_exe()) == 'zig' and arg in {'ar', 'cc', 'c++', 'dlltool', 'lib', 'ranlib', 'objcopy', 'rc'}: + return True diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-python-dep.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-python-dep.patch new file mode 100644 index 000000000..0cbfe717d --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-python-dep.patch @@ -0,0 +1,45 @@ +diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py +index 883a29a..d9a82af 100644 +--- a/mesonbuild/dependencies/python.py ++++ b/mesonbuild/dependencies/python.py +@@ -232,8 +232,10 @@ class _PythonDependencyBase(_Base): + else: + if self.is_freethreaded: + libpath = Path('libs') / f'python{vernum}t.lib' ++ libpath = Path('libs') / f'..' / f'..' / f'..' / f'lib' / f'python{vernum}t.lib' + else: + libpath = Path('libs') / f'python{vernum}.lib' ++ libpath = Path('libs') / f'..' / f'..' / f'..' / f'lib' / f'python{vernum}.lib' + # For a debug build, pyconfig.h may force linking with + # pythonX_d.lib (see meson#10776). This cannot be avoided + # and won't work unless we also have a debug build of +@@ -250,6 +252,8 @@ class _PythonDependencyBase(_Base): + vscrt = self.env.coredata.optstore.get_value('b_vscrt') + if vscrt in {'mdd', 'mtd', 'from_buildtype', 'static_from_buildtype'}: + vscrt_debug = True ++ if is_debug_build: ++ libpath = Path('libs') / f'..' / f'..' / f'..' / f'debug/lib' / f'python{vernum}_d.lib' + if is_debug_build and vscrt_debug and not self.variables.get('Py_DEBUG'): + mlog.warning(textwrap.dedent('''\ + Using a debug build type with MSVC or an MSVC-compatible compiler +@@ -350,9 +354,10 @@ class PythonSystemDependency(SystemDependency, _PythonDependencyBase): + self.is_found = True + + # compile args ++ verdot = self.variables.get('py_version_short') + inc_paths = mesonlib.OrderedSet([ + self.variables.get('INCLUDEPY'), +- self.paths.get('include'), ++ self.paths.get('include') + f'/../../../include/python${verdot}', + self.paths.get('platinclude')]) + + self.compile_args += ['-I' + path for path in inc_paths if path] +@@ -416,7 +421,7 @@ def python_factory(env: 'Environment', for_machine: 'MachineChoice', + candidates.append(functools.partial(wrap_in_pythons_pc_dir, pkg_name, env, kwargs, installation)) + # We only need to check both, if a python install has a LIBPC. It might point to the wrong location, + # e.g. relocated / cross compilation, but the presence of LIBPC indicates we should definitely look for something. +- if pkg_libdir is not None: ++ if True or pkg_libdir is not None: + candidates.append(functools.partial(PythonPkgConfigDependency, pkg_name, env, kwargs, installation)) + else: + candidates.append(functools.partial(PkgConfigDependency, 'python3', env, kwargs)) diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/fix-libcpp-enable-assertions.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/fix-libcpp-enable-assertions.patch new file mode 100644 index 000000000..394b064dc --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/fix-libcpp-enable-assertions.patch @@ -0,0 +1,52 @@ +From a16ec8b0fb6d7035b669a13edd4d97ff0c307a0b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Martin=20D=C3=B8rum?= +Date: Fri, 2 May 2025 10:56:28 +0200 +Subject: [PATCH] cpp: fix _LIBCPP_ENABLE_ASSERTIONS warning + +libc++ deprecated _LIBCPP_ENABLE_ASSERTIONS from version 18. +However, the libc++ shipped with Apple Clang backported that +deprecation in version 17 already, +which is the version which Apple currently ships for macOS. +This PR changes the _LIBCPP_ENABLE_ASSERTIONS deprecation check +to use version ">=17" on Apple Clang. +--- + mesonbuild/compilers/cpp.py | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py +index 01b9bb9fa34f..f7dc150e8608 100644 +--- a/mesonbuild/compilers/cpp.py ++++ b/mesonbuild/compilers/cpp.py +@@ -311,6 +311,9 @@ def get_option_link_args(self, target: 'BuildTarget', env: 'Environment', subpro + return libs + return [] + ++ def is_libcpp_enable_assertions_deprecated(self) -> bool: ++ return version_compare(self.version, ">=18") ++ + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: + if disable: + return ['-DNDEBUG'] +@@ -323,7 +326,7 @@ def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: + if self.language_stdlib_provider(env) == 'stdc++': + return ['-D_GLIBCXX_ASSERTIONS=1'] + else: +- if version_compare(self.version, '>=18'): ++ if self.is_libcpp_enable_assertions_deprecated(): + return ['-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST'] + elif version_compare(self.version, '>=15'): + return ['-D_LIBCPP_ENABLE_ASSERTIONS=1'] +@@ -343,7 +346,12 @@ class ArmLtdClangCPPCompiler(ClangCPPCompiler): + + + class AppleClangCPPCompiler(AppleCompilerMixin, AppleCPPStdsMixin, ClangCPPCompiler): +- pass ++ def is_libcpp_enable_assertions_deprecated(self) -> bool: ++ # Upstream libc++ deprecated _LIBCPP_ENABLE_ASSERTIONS ++ # in favor of _LIBCPP_HARDENING_MODE from version 18 onwards, ++ # but Apple Clang 17's libc++ has back-ported that change. ++ # See: https://github.com/mesonbuild/meson/issues/14440 ++ return version_compare(self.version, ">=17") + + + class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler): diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/install.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/install.cmake new file mode 100644 index 000000000..84201aa1a --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/install.cmake @@ -0,0 +1,5 @@ +file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/tools/meson") +file(INSTALL "${SOURCE_PATH}/meson.py" + "${SOURCE_PATH}/mesonbuild" + DESTINATION "${CURRENT_PACKAGES_DIR}/tools/meson" +) diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/meson-intl.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/meson-intl.patch new file mode 100644 index 000000000..8f2a029de --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/meson-intl.patch @@ -0,0 +1,13 @@ +diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py +--- a/mesonbuild/dependencies/misc.py ++++ b/mesonbuild/dependencies/misc.py +@@ -593,7 +593,8 @@ iconv_factory = DependencyFactory( + + packages['intl'] = intl_factory = DependencyFactory( + 'intl', ++ [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM, DependencyMethods.CMAKE], ++ cmake_name='Intl', +- [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM], + builtin_class=IntlBuiltinDependency, + system_class=IntlSystemDependency, + ) diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/meson.template.in b/cmake/vcpkg-ports/vcpkg-tool-meson/meson.template.in new file mode 100644 index 000000000..df21b753b --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/meson.template.in @@ -0,0 +1,43 @@ +[binaries] +cmake = ['@CMAKE_COMMAND@'] +ninja = ['@NINJA@'] +pkg-config = ['@PKGCONFIG@'] +@MESON_MT@ +@MESON_AR@ +@MESON_RC@ +@MESON_C@ +@MESON_C_LD@ +@MESON_CXX@ +@MESON_CXX_LD@ +@MESON_OBJC@ +@MESON_OBJC_LD@ +@MESON_OBJCPP@ +@MESON_OBJCPP_LD@ +@MESON_FC@ +@MESON_FC_LD@ +@MESON_WINDRES@ +@MESON_ADDITIONAL_BINARIES@ +[properties] +cmake_toolchain_file = '@SCRIPTS@/buildsystems/vcpkg.cmake' +@MESON_ADDITIONAL_PROPERTIES@ +[cmake] +CMAKE_BUILD_TYPE = '@MESON_CMAKE_BUILD_TYPE@' +VCPKG_TARGET_TRIPLET = '@TARGET_TRIPLET@' +VCPKG_HOST_TRIPLET = '@_HOST_TRIPLET@' +VCPKG_CHAINLOAD_TOOLCHAIN_FILE = '@VCPKG_CHAINLOAD_TOOLCHAIN_FILE@' +VCPKG_CRT_LINKAGE = '@VCPKG_CRT_LINKAGE@' +_VCPKG_INSTALLED_DIR = '@_VCPKG_INSTALLED_DIR@' +@MESON_HOST_MACHINE@ +@MESON_BUILD_MACHINE@ +[built-in options] +default_library = '@MESON_DEFAULT_LIBRARY@' +werror = false +@MESON_CFLAGS@ +@MESON_CXXFLAGS@ +@MESON_FCFLAGS@ +@MESON_OBJCFLAGS@ +@MESON_OBJCPPFLAGS@ +# b_vscrt +@MESON_VSCRT_LINKAGE@ +# c_winlibs/cpp_winlibs +@MESON_WINLIBS@ \ No newline at end of file diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/portfile.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/portfile.cmake new file mode 100644 index 000000000..fdea886a7 --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/portfile.cmake @@ -0,0 +1,45 @@ +# This port represents a dependency on the Meson build system. +# In the future, it is expected that this port acquires and installs Meson. +# Currently is used in ports that call vcpkg_find_acquire_program(MESON) in order to force rebuilds. + +set(VCPKG_POLICY_CMAKE_HELPER_PORT enabled) + +set(patches + meson-intl.patch + adjust-python-dep.patch + adjust-args.patch + remove-freebsd-pcfile-specialization.patch + fix-libcpp-enable-assertions.patch # https://github.com/mesonbuild/meson/pull/14548, Remove in 1.8.3 + universal-osx.patch # NOTE(@getchoo): THIS IS THE ONLY CHANGE NEEDED FOR PRISM +) +set(scripts + vcpkg-port-config.cmake + vcpkg_configure_meson.cmake + vcpkg_install_meson.cmake + meson.template.in +) +set(to_hash + "${CMAKE_CURRENT_LIST_DIR}/vcpkg.json" + "${CMAKE_CURRENT_LIST_DIR}/portfile.cmake" +) +foreach(file IN LISTS patches scripts) + set(filepath "${CMAKE_CURRENT_LIST_DIR}/${file}") + list(APPEND to_hash "${filepath}") + file(COPY "${filepath}" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +endforeach() + +set(meson_path_hash "") +foreach(filepath IN LISTS to_hash) + file(SHA1 "${filepath}" to_append) + string(APPEND meson_path_hash "${to_append}") +endforeach() +string(SHA512 meson_path_hash "${meson_path_hash}") + +string(SUBSTRING "${meson_path_hash}" 0 6 MESON_SHORT_HASH) +list(TRANSFORM patches REPLACE [[^(..*)$]] [["${CMAKE_CURRENT_LIST_DIR}/\0"]]) +list(JOIN patches "\n " PATCHES) +configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-port-config.cmake" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-port-config.cmake" @ONLY) + +vcpkg_install_copyright(FILE_LIST "${VCPKG_ROOT_DIR}/LICENSE.txt") + +include("${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-port-config.cmake") diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/remove-freebsd-pcfile-specialization.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/remove-freebsd-pcfile-specialization.patch new file mode 100644 index 000000000..947345ccf --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/remove-freebsd-pcfile-specialization.patch @@ -0,0 +1,23 @@ +diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py +index cc0450a52..13501466d 100644 +--- a/mesonbuild/modules/pkgconfig.py ++++ b/mesonbuild/modules/pkgconfig.py +@@ -701,16 +701,8 @@ class PkgConfigModule(NewExtensionModule): + pcfile = filebase + '.pc' + pkgroot = pkgroot_name = kwargs['install_dir'] or default_install_dir + if pkgroot is None: +- m = state.environment.machines.host +- if m.is_freebsd(): +- pkgroot = os.path.join(_as_str(state.environment.coredata.optstore.get_value_for(OptionKey('prefix'))), 'libdata', 'pkgconfig') +- pkgroot_name = os.path.join('{prefix}', 'libdata', 'pkgconfig') +- elif m.is_haiku(): +- pkgroot = os.path.join(_as_str(state.environment.coredata.optstore.get_value_for(OptionKey('prefix'))), 'develop', 'lib', 'pkgconfig') +- pkgroot_name = os.path.join('{prefix}', 'develop', 'lib', 'pkgconfig') +- else: +- pkgroot = os.path.join(_as_str(state.environment.coredata.optstore.get_value_for(OptionKey('libdir'))), 'pkgconfig') +- pkgroot_name = os.path.join('{libdir}', 'pkgconfig') ++ pkgroot = os.path.join(_as_str(state.environment.coredata.optstore.get_value_for(OptionKey('libdir'))), 'pkgconfig') ++ pkgroot_name = os.path.join('{libdir}', 'pkgconfig') + relocatable = state.get_option('pkgconfig.relocatable') + self._generate_pkgconfig_file(state, deps, subdirs, name, description, url, + version, pcfile, conflicts, variables, diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/universal-osx.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/universal-osx.patch new file mode 100644 index 000000000..58b96d5ce --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/universal-osx.patch @@ -0,0 +1,16 @@ +diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py +index f57957f0b..a72e72a0b 100644 +--- a/mesonbuild/compilers/detect.py ++++ b/mesonbuild/compilers/detect.py +@@ -1472,6 +1472,11 @@ def _get_clang_compiler_defines(compiler: T.List[str], lang: str) -> T.Dict[str, + """ + from .mixins.clang import clang_lang_map + ++ # Filter out `-arch` flags passed to the compiler for Universal Binaries ++ # https://github.com/mesonbuild/meson/issues/5290 ++ # https://github.com/mesonbuild/meson/issues/8206 ++ compiler = [arg for i, arg in enumerate(compiler) if not (i > 0 and compiler[i - 1] == "-arch") and not arg == "-arch"] ++ + def _try_obtain_compiler_defines(args: T.List[str]) -> str: + mlog.debug(f'Running command: {join_args(args)}') + p, output, error = Popen_safe(compiler + args, write='', stdin=subprocess.PIPE) diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg-port-config.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg-port-config.cmake new file mode 100644 index 000000000..c0dee3a38 --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg-port-config.cmake @@ -0,0 +1,62 @@ +include("${CURRENT_HOST_INSTALLED_DIR}/share/vcpkg-cmake-get-vars/vcpkg-port-config.cmake") +# Overwrite builtin scripts +include("${CMAKE_CURRENT_LIST_DIR}/vcpkg_configure_meson.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/vcpkg_install_meson.cmake") + +set(meson_short_hash @MESON_SHORT_HASH@) + +# Setup meson: +set(program MESON) +set(program_version @VERSION@) +set(program_name meson) +set(search_names meson meson.py) +set(ref "${program_version}") +set(path_to_search "${DOWNLOADS}/tools/meson-${program_version}-${meson_short_hash}") +set(download_urls "https://github.com/mesonbuild/meson/archive/${ref}.tar.gz") +set(download_filename "meson-${ref}.tar.gz") +set(download_sha512 bd2e65f0863d9cb974e659ff502d773e937b8a60aaddfd7d81e34cd2c296c8e82bf214d790ac089ba441543059dfc2677ba95ed51f676df9da420859f404a907) + +find_program(SCRIPT_MESON NAMES ${search_names} PATHS "${path_to_search}" NO_DEFAULT_PATH) # NO_DEFAULT_PATH due top patching + +if(NOT SCRIPT_MESON) + vcpkg_download_distfile(archive_path + URLS ${download_urls} + SHA512 "${download_sha512}" + FILENAME "${download_filename}" + ) + file(REMOVE_RECURSE "${path_to_search}") + file(REMOVE_RECURSE "${path_to_search}-tmp") + file(MAKE_DIRECTORY "${path_to_search}-tmp") + file(ARCHIVE_EXTRACT INPUT "${archive_path}" + DESTINATION "${path_to_search}-tmp" + #PATTERNS "**/mesonbuild/*" "**/*.py" + ) + z_vcpkg_apply_patches( + SOURCE_PATH "${path_to_search}-tmp/meson-${ref}" + PATCHES + @PATCHES@ + ) + file(MAKE_DIRECTORY "${path_to_search}") + file(RENAME "${path_to_search}-tmp/meson-${ref}/meson.py" "${path_to_search}/meson.py") + file(RENAME "${path_to_search}-tmp/meson-${ref}/mesonbuild" "${path_to_search}/mesonbuild") + file(REMOVE_RECURSE "${path_to_search}-tmp") + set(SCRIPT_MESON "${path_to_search}/meson.py") +endif() + +# Check required python version +vcpkg_find_acquire_program(PYTHON3) +vcpkg_execute_in_download_mode( + COMMAND "${PYTHON3}" --version + OUTPUT_VARIABLE version_contents + WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}" +) +string(REGEX MATCH [[[0-9]+\.[0-9]+\.[0-9]+]] python_ver "${version_contents}") + +set(min_required 3.7) +if(python_ver VERSION_LESS "${min_required}") + message(FATAL_ERROR "Found Python version '${python_ver} at ${PYTHON3}' is insufficient for meson. meson requires at least version '${min_required}'") +else() + message(STATUS "Found Python version '${python_ver} at ${PYTHON3}'") +endif() + +message(STATUS "Using meson: ${SCRIPT_MESON}") diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg.json b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg.json new file mode 100644 index 000000000..04a0cbbec --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg.json @@ -0,0 +1,11 @@ +{ + "name": "vcpkg-tool-meson", + "version": "1.8.2", + "description": "Meson build system", + "homepage": "https://github.com/mesonbuild/meson", + "license": "Apache-2.0", + "supports": "native", + "dependencies": [ + "vcpkg-cmake-get-vars" + ] +} diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_configure_meson.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_configure_meson.cmake new file mode 100644 index 000000000..6b00200d1 --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_configure_meson.cmake @@ -0,0 +1,480 @@ +function(z_vcpkg_meson_set_proglist_variables config_type) + if(VCPKG_TARGET_IS_WINDOWS) + set(proglist MT AR) + else() + set(proglist AR RANLIB STRIP NM OBJDUMP DLLTOOL MT) + endif() + foreach(prog IN LISTS proglist) + if(VCPKG_DETECTED_CMAKE_${prog}) + if(meson_${prog}) + string(TOUPPER "MESON_${meson_${prog}}" var_to_set) + set("${var_to_set}" "${meson_${prog}} = ['${VCPKG_DETECTED_CMAKE_${prog}}']" PARENT_SCOPE) + elseif(${prog} STREQUAL AR AND VCPKG_COMBINED_STATIC_LINKER_FLAGS_${config_type}) + # Probably need to move AR somewhere else + string(TOLOWER "${prog}" proglower) + z_vcpkg_meson_convert_compiler_flags_to_list(ar_flags "${VCPKG_COMBINED_STATIC_LINKER_FLAGS_${config_type}}") + list(PREPEND ar_flags "${VCPKG_DETECTED_CMAKE_${prog}}") + z_vcpkg_meson_convert_list_to_python_array(ar_flags ${ar_flags}) + set("MESON_AR" "${proglower} = ${ar_flags}" PARENT_SCOPE) + else() + string(TOUPPER "MESON_${prog}" var_to_set) + string(TOLOWER "${prog}" proglower) + set("${var_to_set}" "${proglower} = ['${VCPKG_DETECTED_CMAKE_${prog}}']" PARENT_SCOPE) + endif() + endif() + endforeach() + set(compilers "${arg_LANGUAGES}") + if(VCPKG_TARGET_IS_WINDOWS) + list(APPEND compilers RC) + endif() + set(meson_RC windres) + set(meson_Fortran fortran) + set(meson_CXX cpp) + foreach(prog IN LISTS compilers) + if(VCPKG_DETECTED_CMAKE_${prog}_COMPILER) + string(TOUPPER "MESON_${prog}" var_to_set) + if(meson_${prog}) + if(VCPKG_COMBINED_${prog}_FLAGS_${config_type}) + # Need compiler flags in prog vars for sanity check. + z_vcpkg_meson_convert_compiler_flags_to_list(${prog}flags "${VCPKG_COMBINED_${prog}_FLAGS_${config_type}}") + endif() + list(PREPEND ${prog}flags "${VCPKG_DETECTED_CMAKE_${prog}_COMPILER}") + list(FILTER ${prog}flags EXCLUDE REGEX "(-|/)nologo") # Breaks compiler detection otherwise + z_vcpkg_meson_convert_list_to_python_array(${prog}flags ${${prog}flags}) + set("${var_to_set}" "${meson_${prog}} = ${${prog}flags}" PARENT_SCOPE) + if (DEFINED VCPKG_DETECTED_CMAKE_${prog}_COMPILER_ID + AND NOT VCPKG_DETECTED_CMAKE_${prog}_COMPILER_ID MATCHES "^(GNU|Intel)$" + AND VCPKG_DETECTED_CMAKE_LINKER) + string(TOUPPER "MESON_${prog}_LD" var_to_set) + set(${var_to_set} "${meson_${prog}}_ld = ['${VCPKG_DETECTED_CMAKE_LINKER}']" PARENT_SCOPE) + endif() + else() + if(VCPKG_COMBINED_${prog}_FLAGS_${config_type}) + # Need compiler flags in prog vars for sanity check. + z_vcpkg_meson_convert_compiler_flags_to_list(${prog}flags "${VCPKG_COMBINED_${prog}_FLAGS_${config_type}}") + endif() + list(PREPEND ${prog}flags "${VCPKG_DETECTED_CMAKE_${prog}_COMPILER}") + list(FILTER ${prog}flags EXCLUDE REGEX "(-|/)nologo") # Breaks compiler detection otherwise + z_vcpkg_meson_convert_list_to_python_array(${prog}flags ${${prog}flags}) + string(TOLOWER "${prog}" proglower) + set("${var_to_set}" "${proglower} = ${${prog}flags}" PARENT_SCOPE) + if (DEFINED VCPKG_DETECTED_CMAKE_${prog}_COMPILER_ID + AND NOT VCPKG_DETECTED_CMAKE_${prog}_COMPILER_ID MATCHES "^(GNU|Intel)$" + AND VCPKG_DETECTED_CMAKE_LINKER) + string(TOUPPER "MESON_${prog}_LD" var_to_set) + set(${var_to_set} "${proglower}_ld = ['${VCPKG_DETECTED_CMAKE_LINKER}']" PARENT_SCOPE) + endif() + endif() + endif() + endforeach() +endfunction() + +function(z_vcpkg_meson_convert_compiler_flags_to_list out_var compiler_flags) + separate_arguments(cmake_list NATIVE_COMMAND "${compiler_flags}") + list(TRANSFORM cmake_list REPLACE ";" [[\\;]]) + set("${out_var}" "${cmake_list}" PARENT_SCOPE) +endfunction() + +function(z_vcpkg_meson_convert_list_to_python_array out_var) + z_vcpkg_function_arguments(flag_list 1) + vcpkg_list(REMOVE_ITEM flag_list "") # remove empty elements if any + vcpkg_list(JOIN flag_list "', '" flag_list) + set("${out_var}" "['${flag_list}']" PARENT_SCOPE) +endfunction() + +# Generates the required compiler properties for meson +function(z_vcpkg_meson_set_flags_variables config_type) + if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW) + set(libpath_flag /LIBPATH:) + else() + set(libpath_flag -L) + endif() + if(config_type STREQUAL "DEBUG") + set(path_suffix "/debug") + else() + set(path_suffix "") + endif() + + set(includepath "-I${CURRENT_INSTALLED_DIR}/include") + set(libpath "${libpath_flag}${CURRENT_INSTALLED_DIR}${path_suffix}/lib") + + foreach(lang IN LISTS arg_LANGUAGES) + z_vcpkg_meson_convert_compiler_flags_to_list(${lang}flags "${VCPKG_COMBINED_${lang}_FLAGS_${config_type}}") + if(lang MATCHES "^(C|CXX)$") + vcpkg_list(APPEND ${lang}flags "${includepath}") + endif() + z_vcpkg_meson_convert_list_to_python_array(${lang}flags ${${lang}flags}) + set(lang_mapping "${lang}") + if(lang STREQUAL "Fortran") + set(lang_mapping "FC") + endif() + string(TOLOWER "${lang_mapping}" langlower) + if(lang STREQUAL "CXX") + set(langlower cpp) + endif() + set(MESON_${lang_mapping}FLAGS "${langlower}_args = ${${lang}flags}\n") + set(linker_flags "${VCPKG_COMBINED_SHARED_LINKER_FLAGS_${config_type}}") + z_vcpkg_meson_convert_compiler_flags_to_list(linker_flags "${linker_flags}") + vcpkg_list(APPEND linker_flags "${libpath}") + z_vcpkg_meson_convert_list_to_python_array(linker_flags ${linker_flags}) + string(APPEND MESON_${lang_mapping}FLAGS "${langlower}_link_args = ${linker_flags}\n") + set(MESON_${lang_mapping}FLAGS "${MESON_${lang_mapping}FLAGS}" PARENT_SCOPE) + endforeach() +endfunction() + +function(z_vcpkg_get_build_and_host_system build_system host_system is_cross) #https://mesonbuild.com/Cross-compilation.html + set(build_unknown FALSE) + if(CMAKE_HOST_WIN32) + if(DEFINED ENV{PROCESSOR_ARCHITEW6432}) + set(build_arch $ENV{PROCESSOR_ARCHITEW6432}) + else() + set(build_arch $ENV{PROCESSOR_ARCHITECTURE}) + endif() + if(build_arch MATCHES "(amd|AMD)64") + set(build_cpu_fam x86_64) + set(build_cpu x86_64) + elseif(build_arch MATCHES "(x|X)86") + set(build_cpu_fam x86) + set(build_cpu i686) + elseif(build_arch MATCHES "^(ARM|arm)64$") + set(build_cpu_fam aarch64) + set(build_cpu armv8) + elseif(build_arch MATCHES "^(ARM|arm)$") + set(build_cpu_fam arm) + set(build_cpu armv7hl) + else() + if(NOT DEFINED VCPKG_MESON_CROSS_FILE OR NOT DEFINED VCPKG_MESON_NATIVE_FILE) + message(WARNING "Unsupported build architecture ${build_arch}! Please set VCPKG_MESON_(CROSS|NATIVE)_FILE to a meson file containing the build_machine entry!") + endif() + set(build_unknown TRUE) + endif() + elseif(CMAKE_HOST_UNIX) + # at this stage, CMAKE_HOST_SYSTEM_PROCESSOR is not defined + execute_process( + COMMAND uname -m + OUTPUT_VARIABLE MACHINE + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY) + + # Show real machine architecture to visually understand whether we are in a native Apple Silicon terminal or running under Rosetta emulation + debug_message("Machine: ${MACHINE}") + + if(MACHINE MATCHES "arm64|aarch64") + set(build_cpu_fam aarch64) + set(build_cpu armv8) + elseif(MACHINE MATCHES "armv7h?l") + set(build_cpu_fam arm) + set(build_cpu ${MACHINE}) + elseif(MACHINE MATCHES "x86_64|amd64") + set(build_cpu_fam x86_64) + set(build_cpu x86_64) + elseif(MACHINE MATCHES "x86|i686") + set(build_cpu_fam x86) + set(build_cpu i686) + elseif(MACHINE MATCHES "i386") + set(build_cpu_fam x86) + set(build_cpu i386) + elseif(MACHINE MATCHES "loongarch64") + set(build_cpu_fam loongarch64) + set(build_cpu loongarch64) + else() + # https://github.com/mesonbuild/meson/blob/master/docs/markdown/Reference-tables.md#cpu-families + if(NOT DEFINED VCPKG_MESON_CROSS_FILE OR NOT DEFINED VCPKG_MESON_NATIVE_FILE) + message(WARNING "Unhandled machine: ${MACHINE}! Please set VCPKG_MESON_(CROSS|NATIVE)_FILE to a meson file containing the build_machine entry!") + endif() + set(build_unknown TRUE) + endif() + else() + if(NOT DEFINED VCPKG_MESON_CROSS_FILE OR NOT DEFINED VCPKG_MESON_NATIVE_FILE) + message(WARNING "Failed to detect the build architecture! Please set VCPKG_MESON_(CROSS|NATIVE)_FILE to a meson file containing the build_machine entry!") + endif() + set(build_unknown TRUE) + endif() + + set(build "[build_machine]\n") # Machine the build is performed on + string(APPEND build "endian = 'little'\n") + if(CMAKE_HOST_WIN32) + string(APPEND build "system = 'windows'\n") + elseif(CMAKE_HOST_APPLE) + string(APPEND build "system = 'darwin'\n") + elseif(CYGWIN) + string(APPEND build "system = 'cygwin'\n") + elseif(CMAKE_HOST_UNIX) + string(APPEND build "system = 'linux'\n") + else() + set(build_unknown TRUE) + endif() + + if(DEFINED build_cpu_fam) + string(APPEND build "cpu_family = '${build_cpu_fam}'\n") + endif() + if(DEFINED build_cpu) + string(APPEND build "cpu = '${build_cpu}'") + endif() + if(NOT build_unknown) + set(${build_system} "${build}" PARENT_SCOPE) + endif() + + set(host_unkown FALSE) + if(VCPKG_TARGET_ARCHITECTURE MATCHES "(amd|AMD|x|X)64") + set(host_cpu_fam x86_64) + set(host_cpu x86_64) + elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "(x|X)86") + set(host_cpu_fam x86) + set(host_cpu i686) + elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "^(ARM|arm)64$") + set(host_cpu_fam aarch64) + set(host_cpu armv8) + elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "^(ARM|arm)$") + set(host_cpu_fam arm) + set(host_cpu armv7hl) + elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "loongarch64") + set(host_cpu_fam loongarch64) + set(host_cpu loongarch64) + elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "wasm32") + set(host_cpu_fam wasm32) + set(host_cpu wasm32) + else() + if(NOT DEFINED VCPKG_MESON_CROSS_FILE OR NOT DEFINED VCPKG_MESON_NATIVE_FILE) + message(WARNING "Unsupported target architecture ${VCPKG_TARGET_ARCHITECTURE}! Please set VCPKG_MESON_(CROSS|NATIVE)_FILE to a meson file containing the host_machine entry!" ) + endif() + set(host_unkown TRUE) + endif() + + set(host "[host_machine]\n") # host=target in vcpkg. + string(APPEND host "endian = 'little'\n") + if(NOT VCPKG_CMAKE_SYSTEM_NAME OR VCPKG_TARGET_IS_MINGW OR VCPKG_TARGET_IS_UWP) + set(meson_system_name "windows") + else() + string(TOLOWER "${VCPKG_CMAKE_SYSTEM_NAME}" meson_system_name) + endif() + string(APPEND host "system = '${meson_system_name}'\n") + string(APPEND host "cpu_family = '${host_cpu_fam}'\n") + string(APPEND host "cpu = '${host_cpu}'") + if(NOT host_unkown) + set(${host_system} "${host}" PARENT_SCOPE) + endif() + + if(NOT build_cpu_fam MATCHES "${host_cpu_fam}" + OR VCPKG_TARGET_IS_ANDROID OR VCPKG_TARGET_IS_IOS OR VCPKG_TARGET_IS_UWP + OR (VCPKG_TARGET_IS_MINGW AND NOT CMAKE_HOST_WIN32)) + set(${is_cross} TRUE PARENT_SCOPE) + endif() +endfunction() + +function(z_vcpkg_meson_setup_extra_windows_variables config_type) + ## b_vscrt + if(VCPKG_CRT_LINKAGE STREQUAL "static") + set(crt_type "mt") + else() + set(crt_type "md") + endif() + if(config_type STREQUAL "DEBUG") + set(crt_type "${crt_type}d") + endif() + set(MESON_VSCRT_LINKAGE "b_vscrt = '${crt_type}'" PARENT_SCOPE) + ## winlibs + separate_arguments(c_winlibs NATIVE_COMMAND "${VCPKG_DETECTED_CMAKE_C_STANDARD_LIBRARIES}") + separate_arguments(cpp_winlibs NATIVE_COMMAND "${VCPKG_DETECTED_CMAKE_CXX_STANDARD_LIBRARIES}") + z_vcpkg_meson_convert_list_to_python_array(c_winlibs ${c_winlibs}) + z_vcpkg_meson_convert_list_to_python_array(cpp_winlibs ${cpp_winlibs}) + set(MESON_WINLIBS "c_winlibs = ${c_winlibs}\n") + string(APPEND MESON_WINLIBS "cpp_winlibs = ${cpp_winlibs}") + set(MESON_WINLIBS "${MESON_WINLIBS}" PARENT_SCOPE) +endfunction() + +function(z_vcpkg_meson_setup_variables config_type) + set(meson_var_list VSCRT_LINKAGE WINLIBS MT AR RC C C_LD CXX CXX_LD OBJC OBJC_LD OBJCXX OBJCXX_LD FC FC_LD WINDRES CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS FCFLAGS SHARED_LINKER_FLAGS) + foreach(var IN LISTS meson_var_list) + set(MESON_${var} "") + endforeach() + + if(VCPKG_TARGET_IS_WINDOWS) + z_vcpkg_meson_setup_extra_windows_variables("${config_type}") + endif() + + z_vcpkg_meson_set_proglist_variables("${config_type}") + z_vcpkg_meson_set_flags_variables("${config_type}") + + foreach(var IN LISTS meson_var_list) + set(MESON_${var} "${MESON_${var}}" PARENT_SCOPE) + endforeach() +endfunction() + +function(vcpkg_generate_meson_cmd_args) + cmake_parse_arguments(PARSE_ARGV 0 arg + "" + "OUTPUT;CONFIG" + "OPTIONS;LANGUAGES;ADDITIONAL_BINARIES;ADDITIONAL_PROPERTIES" + ) + + if(NOT arg_LANGUAGES) + set(arg_LANGUAGES C CXX) + endif() + + vcpkg_list(JOIN arg_ADDITIONAL_BINARIES "\n" MESON_ADDITIONAL_BINARIES) + vcpkg_list(JOIN arg_ADDITIONAL_PROPERTIES "\n" MESON_ADDITIONAL_PROPERTIES) + + set(buildtype "${arg_CONFIG}") + + if(NOT VCPKG_CHAINLOAD_TOOLCHAIN_FILE) + z_vcpkg_select_default_vcpkg_chainload_toolchain() + endif() + vcpkg_list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS "-DVCPKG_LANGUAGES=${arg_LANGUAGES}") + vcpkg_cmake_get_vars(cmake_vars_file) + debug_message("Including cmake vars from: ${cmake_vars_file}") + include("${cmake_vars_file}") + + vcpkg_list(APPEND arg_OPTIONS --backend ninja --wrap-mode nodownload -Doptimization=plain) + + z_vcpkg_get_build_and_host_system(MESON_HOST_MACHINE MESON_BUILD_MACHINE IS_CROSS) + + if(arg_CONFIG STREQUAL "DEBUG") + set(suffix "dbg") + else() + string(SUBSTRING "${arg_CONFIG}" 0 3 suffix) + string(TOLOWER "${suffix}" suffix) + endif() + set(meson_input_file_${buildtype} "${CURRENT_BUILDTREES_DIR}/meson-${TARGET_TRIPLET}-${suffix}.log") + + if(IS_CROSS) + # VCPKG_CROSSCOMPILING is not used since it regresses a lot of ports in x64-windows-x triplets + # For consistency this should proably be changed in the future? + vcpkg_list(APPEND arg_OPTIONS --native "${SCRIPTS}/buildsystems/meson/none.txt") + vcpkg_list(APPEND arg_OPTIONS --cross "${meson_input_file_${buildtype}}") + else() + vcpkg_list(APPEND arg_OPTIONS --native "${meson_input_file_${buildtype}}") + endif() + + # User provided cross/native files + if(VCPKG_MESON_NATIVE_FILE) + vcpkg_list(APPEND arg_OPTIONS --native "${VCPKG_MESON_NATIVE_FILE}") + endif() + if(VCPKG_MESON_NATIVE_FILE_${buildtype}) + vcpkg_list(APPEND arg_OPTIONS --native "${VCPKG_MESON_NATIVE_FILE_${buildtype}}") + endif() + if(VCPKG_MESON_CROSS_FILE) + vcpkg_list(APPEND arg_OPTIONS --cross "${VCPKG_MESON_CROSS_FILE}") + endif() + if(VCPKG_MESON_CROSS_FILE_${buildtype}) + vcpkg_list(APPEND arg_OPTIONS --cross "${VCPKG_MESON_CROSS_FILE_${buildtype}}") + endif() + + vcpkg_list(APPEND arg_OPTIONS --libdir lib) # else meson install into an architecture describing folder + vcpkg_list(APPEND arg_OPTIONS --pkgconfig.relocatable) + + if(arg_CONFIG STREQUAL "RELEASE") + vcpkg_list(APPEND arg_OPTIONS -Ddebug=false --prefix "${CURRENT_PACKAGES_DIR}") + vcpkg_list(APPEND arg_OPTIONS "--pkg-config-path;['${CURRENT_INSTALLED_DIR}/lib/pkgconfig','${CURRENT_INSTALLED_DIR}/share/pkgconfig']") + if(VCPKG_TARGET_IS_WINDOWS) + vcpkg_list(APPEND arg_OPTIONS "-Dcmake_prefix_path=['${CURRENT_INSTALLED_DIR}','${CURRENT_INSTALLED_DIR}/debug','${CURRENT_INSTALLED_DIR}/share']") + else() + vcpkg_list(APPEND arg_OPTIONS "-Dcmake_prefix_path=['${CURRENT_INSTALLED_DIR}','${CURRENT_INSTALLED_DIR}/debug']") + endif() + elseif(arg_CONFIG STREQUAL "DEBUG") + vcpkg_list(APPEND arg_OPTIONS -Ddebug=true --prefix "${CURRENT_PACKAGES_DIR}/debug" --includedir ../include) + vcpkg_list(APPEND arg_OPTIONS "--pkg-config-path;['${CURRENT_INSTALLED_DIR}/debug/lib/pkgconfig','${CURRENT_INSTALLED_DIR}/share/pkgconfig']") + if(VCPKG_TARGET_IS_WINDOWS) + vcpkg_list(APPEND arg_OPTIONS "-Dcmake_prefix_path=['${CURRENT_INSTALLED_DIR}/debug','${CURRENT_INSTALLED_DIR}','${CURRENT_INSTALLED_DIR}/share']") + else() + vcpkg_list(APPEND arg_OPTIONS "-Dcmake_prefix_path=['${CURRENT_INSTALLED_DIR}/debug','${CURRENT_INSTALLED_DIR}']") + endif() + else() + message(FATAL_ERROR "Unknown configuration. Only DEBUG and RELEASE are valid values.") + endif() + + # Allow overrides / additional configuration variables from triplets + if(DEFINED VCPKG_MESON_CONFIGURE_OPTIONS) + vcpkg_list(APPEND arg_OPTIONS ${VCPKG_MESON_CONFIGURE_OPTIONS}) + endif() + if(DEFINED VCPKG_MESON_CONFIGURE_OPTIONS_${buildtype}) + vcpkg_list(APPEND arg_OPTIONS ${VCPKG_MESON_CONFIGURE_OPTIONS_${buildtype}}) + endif() + + if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic") + set(MESON_DEFAULT_LIBRARY shared) + else() + set(MESON_DEFAULT_LIBRARY static) + endif() + set(MESON_CMAKE_BUILD_TYPE "${cmake_build_type_${buildtype}}") + z_vcpkg_meson_setup_variables(${buildtype}) + configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/meson.template.in" "${meson_input_file_${buildtype}}" @ONLY) + set("${arg_OUTPUT}" ${arg_OPTIONS} PARENT_SCOPE) +endfunction() + +function(vcpkg_configure_meson) + # parse parameters such that semicolons in options arguments to COMMAND don't get erased + cmake_parse_arguments(PARSE_ARGV 0 arg + "NO_PKG_CONFIG" + "SOURCE_PATH" + "OPTIONS;OPTIONS_DEBUG;OPTIONS_RELEASE;LANGUAGES;ADDITIONAL_BINARIES;ADDITIONAL_NATIVE_BINARIES;ADDITIONAL_CROSS_BINARIES;ADDITIONAL_PROPERTIES" + ) + + if(DEFINED arg_ADDITIONAL_NATIVE_BINARIES OR DEFINED arg_ADDITIONAL_CROSS_BINARIES) + message(WARNING "Options ADDITIONAL_(NATIVE|CROSS)_BINARIES have been deprecated. Only use ADDITIONAL_BINARIES!") + endif() + vcpkg_list(APPEND arg_ADDITIONAL_BINARIES ${arg_ADDITIONAL_NATIVE_BINARIES} ${arg_ADDITIONAL_CROSS_BINARIES}) + vcpkg_list(REMOVE_DUPLICATES arg_ADDITIONAL_BINARIES) + + file(REMOVE_RECURSE "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel") + file(REMOVE_RECURSE "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg") + + vcpkg_find_acquire_program(MESON) + + get_filename_component(CMAKE_PATH "${CMAKE_COMMAND}" DIRECTORY) + vcpkg_add_to_path("${CMAKE_PATH}") # Make CMake invokeable for Meson + + vcpkg_find_acquire_program(NINJA) + + if(NOT arg_NO_PKG_CONFIG) + vcpkg_find_acquire_program(PKGCONFIG) + set(ENV{PKG_CONFIG} "${PKGCONFIG}") + endif() + + vcpkg_find_acquire_program(PYTHON3) + get_filename_component(PYTHON3_DIR "${PYTHON3}" DIRECTORY) + vcpkg_add_to_path(PREPEND "${PYTHON3_DIR}") + + set(buildtypes "") + if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + set(buildname "DEBUG") + set(cmake_build_type_${buildname} "Debug") + vcpkg_list(APPEND buildtypes "${buildname}") + set(path_suffix_${buildname} "debug/") + set(suffix_${buildname} "dbg") + endif() + if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + set(buildname "RELEASE") + set(cmake_build_type_${buildname} "Release") + vcpkg_list(APPEND buildtypes "${buildname}") + set(path_suffix_${buildname} "") + set(suffix_${buildname} "rel") + endif() + + # configure build + foreach(buildtype IN LISTS buildtypes) + message(STATUS "Configuring ${TARGET_TRIPLET}-${suffix_${buildtype}}") + file(MAKE_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${suffix_${buildtype}}") + + vcpkg_generate_meson_cmd_args( + OUTPUT cmd_args + CONFIG ${buildtype} + LANGUAGES ${arg_LANGUAGES} + OPTIONS ${arg_OPTIONS} ${arg_OPTIONS_${buildtype}} + ADDITIONAL_BINARIES ${arg_ADDITIONAL_BINARIES} + ADDITIONAL_PROPERTIES ${arg_ADDITIONAL_PROPERTIES} + ) + + vcpkg_execute_required_process( + COMMAND ${MESON} setup ${cmd_args} ${arg_SOURCE_PATH} + WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${suffix_${buildtype}}" + LOGNAME config-${TARGET_TRIPLET}-${suffix_${buildtype}} + SAVE_LOG_FILES + meson-logs/meson-log.txt + meson-info/intro-dependencies.json + meson-logs/install-log.txt + ) + + message(STATUS "Configuring ${TARGET_TRIPLET}-${suffix_${buildtype}} done") + endforeach() +endfunction() diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_install_meson.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_install_meson.cmake new file mode 100644 index 000000000..0351f271a --- /dev/null +++ b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_install_meson.cmake @@ -0,0 +1,71 @@ +function(vcpkg_install_meson) + cmake_parse_arguments(PARSE_ARGV 0 arg "ADD_BIN_TO_PATH" "" "") + + vcpkg_find_acquire_program(NINJA) + unset(ENV{DESTDIR}) # installation directory was already specified with '--prefix' option + + if(VCPKG_TARGET_IS_OSX) + vcpkg_backup_env_variables(VARS SDKROOT MACOSX_DEPLOYMENT_TARGET) + set(ENV{SDKROOT} "${VCPKG_DETECTED_CMAKE_OSX_SYSROOT}") + set(ENV{MACOSX_DEPLOYMENT_TARGET} "${VCPKG_DETECTED_CMAKE_OSX_DEPLOYMENT_TARGET}") + endif() + + foreach(buildtype IN ITEMS "debug" "release") + if(DEFINED VCPKG_BUILD_TYPE AND NOT VCPKG_BUILD_TYPE STREQUAL buildtype) + continue() + endif() + + if(buildtype STREQUAL "debug") + set(short_buildtype "dbg") + else() + set(short_buildtype "rel") + endif() + + message(STATUS "Package ${TARGET_TRIPLET}-${short_buildtype}") + if(arg_ADD_BIN_TO_PATH) + vcpkg_backup_env_variables(VARS PATH) + if(buildtype STREQUAL "debug") + vcpkg_add_to_path(PREPEND "${CURRENT_INSTALLED_DIR}/debug/bin") + else() + vcpkg_add_to_path(PREPEND "${CURRENT_INSTALLED_DIR}/bin") + endif() + endif() + vcpkg_execute_required_process( + COMMAND "${NINJA}" install -v + WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${short_buildtype}" + LOGNAME package-${TARGET_TRIPLET}-${short_buildtype} + ) + if(arg_ADD_BIN_TO_PATH) + vcpkg_restore_env_variables(VARS PATH) + endif() + endforeach() + + vcpkg_list(SET renamed_libs) + if(VCPKG_TARGET_IS_WINDOWS AND VCPKG_LIBRARY_LINKAGE STREQUAL static AND NOT VCPKG_TARGET_IS_MINGW) + # Meson names all static libraries lib.a which basically breaks the world + file(GLOB_RECURSE gen_libraries "${CURRENT_PACKAGES_DIR}*/**/lib*.a") + foreach(gen_library IN LISTS gen_libraries) + get_filename_component(libdir "${gen_library}" DIRECTORY) + get_filename_component(libname "${gen_library}" NAME) + string(REGEX REPLACE ".a$" ".lib" fixed_librawname "${libname}") + string(REGEX REPLACE "^lib" "" fixed_librawname "${fixed_librawname}") + file(RENAME "${gen_library}" "${libdir}/${fixed_librawname}") + # For cmake fixes. + string(REGEX REPLACE ".a$" "" origin_librawname "${libname}") + string(REGEX REPLACE ".lib$" "" fixed_librawname "${fixed_librawname}") + vcpkg_list(APPEND renamed_libs ${fixed_librawname}) + set(${librawname}_old ${origin_librawname}) + set(${librawname}_new ${fixed_librawname}) + endforeach() + file(GLOB_RECURSE cmake_files "${CURRENT_PACKAGES_DIR}*/*.cmake") + foreach(cmake_file IN LISTS cmake_files) + foreach(current_lib IN LISTS renamed_libs) + vcpkg_replace_string("${cmake_file}" "${${current_lib}_old}" "${${current_lib}_new}" IGNORE_UNCHANGED) + endforeach() + endforeach() + endif() + + if(VCPKG_TARGET_IS_OSX) + vcpkg_restore_env_variables(VARS SDKROOT MACOSX_DEPLOYMENT_TARGET) + endif() +endfunction() diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json index 3a59b2658..71db4bcca 100644 --- a/vcpkg-configuration.json +++ b/vcpkg-configuration.json @@ -11,6 +11,9 @@ "name": "microsoft" } ], + "overlay-ports": [ + "./cmake/vcpkg-ports" + ], "overlay-triplets": [ "./cmake/vcpkg-triplets" ] From a8eea411e97475aa4bdf135d272db571ca9e4e53 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 23 Jul 2025 23:28:11 +0000 Subject: [PATCH 071/118] chore(deps): update cachix/install-nix-action digest to c134e4c --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index de341b517..5822c411b 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31 + - uses: cachix/install-nix-action@c134e4c9e34bac6cab09cf239815f9339aaaf84e # v31 - uses: DeterminateSystems/update-flake-lock@v27 with: From 2e428330f4933b128f45717b3b13eaa2463ed5ae Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 18 Jan 2025 15:39:25 +0200 Subject: [PATCH 072/118] support gif catpacks Signed-off-by: Trial97 --- launcher/ui/themes/CatPainter.cpp | 17 ++++++++++++++++- launcher/ui/themes/CatPainter.h | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/launcher/ui/themes/CatPainter.cpp b/launcher/ui/themes/CatPainter.cpp index 7ff24932b..7c152fdc9 100644 --- a/launcher/ui/themes/CatPainter.cpp +++ b/launcher/ui/themes/CatPainter.cpp @@ -22,12 +22,27 @@ CatPainter::CatPainter(const QString& path, QObject* parent) : QObject(parent) { - m_image = QPixmap(path); + // Attempt to load as a movie + m_movie = new QMovie(path, QByteArray(), this); + if (m_movie->isValid()) { + // Start the animation if it's a valid movie file + connect(m_movie, &QMovie::frameChanged, this, &CatPainter::updateFrame); + m_movie->start(); + } else { + // Otherwise, load it as a static image + delete m_movie; + m_movie = nullptr; + + m_image = QPixmap(path); + } } void CatPainter::paint(QPainter* painter, const QRect& viewport) { QPixmap frame = m_image; + if (m_movie && m_movie->isValid()) { + frame = m_movie->currentPixmap(); + } auto fit = APPLICATION->settings()->get("CatFit").toString(); painter->setOpacity(APPLICATION->settings()->get("CatOpacity").toFloat() / 100); diff --git a/launcher/ui/themes/CatPainter.h b/launcher/ui/themes/CatPainter.h index 3b790c640..c36cb7617 100644 --- a/launcher/ui/themes/CatPainter.h +++ b/launcher/ui/themes/CatPainter.h @@ -34,5 +34,6 @@ class CatPainter : public QObject { void updateFrame(); private: + QMovie* m_movie = nullptr; QPixmap m_image; }; From 597309ceeb7aff9f429f2567a8e97929cf316cdd Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 24 Jul 2025 18:44:46 +0300 Subject: [PATCH 073/118] ensure that both cape and skin are downloaded via https Signed-off-by: Trial97 --- launcher/minecraft/auth/AccountData.cpp | 2 ++ launcher/minecraft/auth/Parsers.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp index 161fd968c..29a65e275 100644 --- a/launcher/minecraft/auth/AccountData.cpp +++ b/launcher/minecraft/auth/AccountData.cpp @@ -180,6 +180,7 @@ MinecraftProfile profileFromJSONV3(const QJsonObject& parent, const char* tokenN } out.skin.id = idV.toString(); out.skin.url = urlV.toString(); + out.skin.url.replace("http://textures.minecraft.net", "https://textures.minecraft.net"); out.skin.variant = variantV.toString(); // data for skin is optional @@ -216,6 +217,7 @@ MinecraftProfile profileFromJSONV3(const QJsonObject& parent, const char* tokenN Cape cape; cape.id = idV.toString(); cape.url = urlV.toString(); + cape.url.replace("http://textures.minecraft.net", "https://textures.minecraft.net"); cape.alias = aliasV.toString(); // data for cape is optional. diff --git a/launcher/minecraft/auth/Parsers.cpp b/launcher/minecraft/auth/Parsers.cpp index de1ffda86..ba77d3e31 100644 --- a/launcher/minecraft/auth/Parsers.cpp +++ b/launcher/minecraft/auth/Parsers.cpp @@ -207,6 +207,7 @@ bool parseMinecraftProfile(QByteArray& data, MinecraftProfile& output) if (!getString(capeObj.value("url"), capeOut.url)) { continue; } + capeOut.url.replace("http://textures.minecraft.net", "https://textures.minecraft.net"); if (!getString(capeObj.value("alias"), capeOut.alias)) { continue; } @@ -358,6 +359,7 @@ bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output) qWarning() << "Skin url is not a string"; return false; } + skinOut.url.replace("http://textures.minecraft.net", "https://textures.minecraft.net"); auto maybeMeta = skin.find("metadata"); if (maybeMeta != skin.end() && maybeMeta->isObject()) { @@ -371,6 +373,7 @@ bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output) qWarning() << "Cape url is not a string"; return false; } + capeOut.url.replace("http://textures.minecraft.net", "https://textures.minecraft.net"); // we don't know the cape ID as it is not returned from the session server // so just fake it - changing capes is probably locked anyway :( From eefe0375af0b8be810781952cffe9368db1cec53 Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Sat, 26 Jul 2025 18:41:34 +0500 Subject: [PATCH 074/118] fix(mojang api): use new endpoint for Username->UUID resolution Signed-off-by: Octol1ttle --- launcher/ui/dialogs/skins/SkinManageDialog.cpp | 2 +- .../legacy/org/prismlauncher/legacy/utils/api/MojangApi.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/dialogs/skins/SkinManageDialog.cpp b/launcher/ui/dialogs/skins/SkinManageDialog.cpp index e7c06d048..5967281c4 100644 --- a/launcher/ui/dialogs/skins/SkinManageDialog.cpp +++ b/launcher/ui/dialogs/skins/SkinManageDialog.cpp @@ -446,7 +446,7 @@ void SkinManageDialog::on_userBtn_clicked() auto uuidLoop = makeShared(); auto profileLoop = makeShared(); - auto getUUID = Net::Download::makeByteArray("https://api.mojang.com/users/profiles/minecraft/" + user, uuidOut); + auto getUUID = Net::Download::makeByteArray("https://api.minecraftservices.com/minecraft/profile/lookup/name/" + user, uuidOut); auto getProfile = Net::Download::makeByteArray(QUrl(), profileOut); auto downloadSkin = Net::Download::makeFile(QUrl(), path); diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java index 41f7f9114..34313e91a 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java @@ -49,7 +49,7 @@ import java.util.Map; @SuppressWarnings("unchecked") public final class MojangApi { public static String getUuid(String username) throws IOException { - try (InputStream in = new URL("https://api.mojang.com/users/profiles/minecraft/" + username).openStream()) { + try (InputStream in = new URL("https://api.minecraftservices.com/minecraft/profile/lookup/name/" + username).openStream()) { Map map = (Map) JsonParser.parse(in); return (String) map.get("id"); } From f40117b4318a1c4d9fd1b94b67124210d1f92d49 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 27 Jul 2025 12:58:59 +0300 Subject: [PATCH 075/118] update ftb import to consider meta folder Signed-off-by: Trial97 --- .../modplatform/import_ftb/PackHelpers.cpp | 39 ++++++++++++++++++- .../modplatform/import_ftb/ImportFTBPage.cpp | 38 +++++++++++++++++- .../modplatform/import_ftb/ListModel.cpp | 1 - 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/import_ftb/PackHelpers.cpp b/launcher/modplatform/import_ftb/PackHelpers.cpp index e523b9d20..089b5fff2 100644 --- a/launcher/modplatform/import_ftb/PackHelpers.cpp +++ b/launcher/modplatform/import_ftb/PackHelpers.cpp @@ -19,6 +19,7 @@ #include "modplatform/import_ftb/PackHelpers.h" #include +#include #include #include @@ -27,6 +28,35 @@ namespace FTBImportAPP { +QIcon loadFTBIcon(const QString& imagePath) +{ + // Map of type byte to image type string + static const QHash imageTypeMap = { { 0x00, "png" }, { 0x01, "jpg" }, { 0x02, "gif" }, { 0x03, "webp" } }; + QFile file(imagePath); + if (!file.exists() || !file.open(QIODevice::ReadOnly)) { + return QIcon(); + } + char type; + if (!file.getChar(&type)) { + qDebug() << "Missing FTB image type header at" << imagePath; + return QIcon(); + } + if (!imageTypeMap.contains(type)) { + qDebug().nospace().noquote() << "Don't recognize FTB image type 0x" << QString::number(type, 16); + return QIcon(); + } + + auto imageType = imageTypeMap[type]; + // Extract actual image data beyond the first byte + QImageReader reader(&file, imageType); + auto pixmap = QPixmap::fromImageReader(&reader); + if (pixmap.isNull()) { + qDebug() << "The FTB image at" << imagePath << "is not valid"; + return QIcon(); + } + return QIcon(pixmap); +} + Modpack parseDirectory(QString path) { Modpack modpack{ path }; @@ -48,9 +78,14 @@ Modpack parseDirectory(QString path) qDebug() << "Couldn't load ftb instance json: " << e.cause(); return {}; } + auto versionsFile = QFileInfo(FS::PathCombine(path, "version.json")); - if (!versionsFile.exists() || !versionsFile.isFile()) + if (!versionsFile.exists() || !versionsFile.isFile()) { + versionsFile = QFileInfo(FS::PathCombine(path, ".ftbapp", "version.json")); + } + if (!versionsFile.exists() || !versionsFile.isFile()) { return {}; + } try { auto doc = Json::requireDocument(versionsFile.absoluteFilePath(), "FTB_APP version JSON file"); const auto root = doc.object(); @@ -85,6 +120,8 @@ Modpack parseDirectory(QString path) auto iconFile = QFileInfo(FS::PathCombine(path, "folder.jpg")); if (iconFile.exists() && iconFile.isFile()) { modpack.icon = QIcon(iconFile.absoluteFilePath()); + } else { // the logo is a file that the first bit denotes the image tipe followed by the actual image data + modpack.icon = loadFTBIcon(FS::PathCombine(path, ".ftbapp", "logo")); } return modpack; } diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp index 35e1dc110..9a2b31768 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include "FileSystem.h" #include "ListModel.h" @@ -88,6 +89,34 @@ void ImportFTBPage::retranslate() ui->retranslateUi(this); } +QString saveIconToTempFile(const QIcon& icon) +{ + if (icon.isNull()) { + return QString(); + } + + QPixmap pixmap = icon.pixmap(icon.availableSizes().last()); + if (pixmap.isNull()) { + return QString(); + } + + QTemporaryFile tempFile(QDir::tempPath() + "/iconXXXXXX.png"); + tempFile.setAutoRemove(false); + if (!tempFile.open()) { + return QString(); + } + + QString tempPath = tempFile.fileName(); + tempFile.close(); + + if (!pixmap.save(tempPath, "PNG")) { + QFile::remove(tempPath); + return QString(); + } + + return tempPath; // Success +} + void ImportFTBPage::suggestCurrent() { if (!isOpened) @@ -100,7 +129,14 @@ void ImportFTBPage::suggestCurrent() dialog->setSuggestedPack(selected.name, new PackInstallTask(selected)); QString editedLogoName = QString("ftb_%1_%2.jpg").arg(selected.name, QString::number(selected.id)); - dialog->setSuggestedIconFromFile(FS::PathCombine(selected.path, "folder.jpg"), editedLogoName); + auto iconPath = FS::PathCombine(selected.path, "folder.jpg"); + if (!QFileInfo::exists(iconPath)) { + // need to save the icon as that actual logo is not a image on the disk + iconPath = saveIconToTempFile(selected.icon); + } + if (!iconPath.isEmpty() && QFileInfo::exists(iconPath)) { + dialog->setSuggestedIconFromFile(iconPath, editedLogoName); + } } void ImportFTBPage::onPublicPackSelectionChanged(QModelIndex now, QModelIndex) diff --git a/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp index 8d3beea01..daa2189ad 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp @@ -17,7 +17,6 @@ */ #include "ListModel.h" -#include #include #include #include From 29231e2038f57b72cc71fb1c20cd8f052cb35377 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 9 Jul 2025 18:43:24 +0300 Subject: [PATCH 076/118] chore: update to cxx20 Signed-off-by: Trial97 --- CMakeLists.txt | 2 +- launcher/java/JavaVersion.cpp | 6 +++--- launcher/java/JavaVersion.h | 6 +++--- launcher/modplatform/ResourceAPI.h | 11 ----------- 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 929e1b394..1360b82ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/jars) ######## Set compiler flags ######## set(CMAKE_CXX_STANDARD_REQUIRED true) set(CMAKE_C_STANDARD_REQUIRED true) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_C_STANDARD 11) include(GenerateExportHeader) if(MSVC) diff --git a/launcher/java/JavaVersion.cpp b/launcher/java/JavaVersion.cpp index e9a160ea7..fef573c16 100644 --- a/launcher/java/JavaVersion.cpp +++ b/launcher/java/JavaVersion.cpp @@ -63,7 +63,7 @@ bool JavaVersion::isModular() const return m_parseable && m_major >= 9; } -bool JavaVersion::operator<(const JavaVersion& rhs) +bool JavaVersion::operator<(const JavaVersion& rhs) const { if (m_parseable && rhs.m_parseable) { auto major = m_major; @@ -101,7 +101,7 @@ bool JavaVersion::operator<(const JavaVersion& rhs) return StringUtils::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0; } -bool JavaVersion::operator==(const JavaVersion& rhs) +bool JavaVersion::operator==(const JavaVersion& rhs) const { if (m_parseable && rhs.m_parseable) { return m_major == rhs.m_major && m_minor == rhs.m_minor && m_security == rhs.m_security && m_prerelease == rhs.m_prerelease; @@ -109,7 +109,7 @@ bool JavaVersion::operator==(const JavaVersion& rhs) return m_string == rhs.m_string; } -bool JavaVersion::operator>(const JavaVersion& rhs) +bool JavaVersion::operator>(const JavaVersion& rhs) const { return (!operator<(rhs)) && (!operator==(rhs)); } diff --git a/launcher/java/JavaVersion.h b/launcher/java/JavaVersion.h index c070bdeec..143ddd262 100644 --- a/launcher/java/JavaVersion.h +++ b/launcher/java/JavaVersion.h @@ -20,9 +20,9 @@ class JavaVersion { JavaVersion& operator=(const QString& rhs); - bool operator<(const JavaVersion& rhs); - bool operator==(const JavaVersion& rhs); - bool operator>(const JavaVersion& rhs); + bool operator<(const JavaVersion& rhs) const; + bool operator==(const JavaVersion& rhs) const; + bool operator>(const JavaVersion& rhs) const; bool requiresPermGen() const; bool defaultsToUtf8() const; diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 6641628f6..4d40432ee 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -90,14 +90,6 @@ class ResourceAPI { std::optional> mcVersions; std::optional loaders; - - VersionSearchArgs(VersionSearchArgs const&) = default; - void operator=(VersionSearchArgs other) - { - pack = other.pack; - mcVersions = other.mcVersions; - loaders = other.loaders; - } }; struct VersionSearchCallbacks { std::function on_succeed; @@ -106,9 +98,6 @@ class ResourceAPI { struct ProjectInfoArgs { ModPlatform::IndexedPack pack; - - ProjectInfoArgs(ProjectInfoArgs const&) = default; - void operator=(ProjectInfoArgs other) { pack = other.pack; } }; struct ProjectInfoCallbacks { std::function on_succeed; From b196c5d59fde3cac29f93fe5a8351629e95abf9c Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Thu, 31 Jul 2025 20:11:16 -0400 Subject: [PATCH 077/118] ci(setup-deps/windows): install java Signed-off-by: Seth Flynn --- .github/actions/setup-dependencies/windows/action.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/actions/setup-dependencies/windows/action.yml b/.github/actions/setup-dependencies/windows/action.yml index 97033747e..9b045610e 100644 --- a/.github/actions/setup-dependencies/windows/action.yml +++ b/.github/actions/setup-dependencies/windows/action.yml @@ -25,6 +25,14 @@ runs: arch: ${{ inputs.vcvars-arch }} vsversion: 2022 + - name: Setup Java (MSVC) + uses: actions/setup-java@v4 + with: + # NOTE(@getchoo): We should probably stay on Zulu. + # Temurin doesn't have Java 17 builds for WoA + distribution: zulu + java-version: 17 + - name: Setup vcpkg cache (MSVC) if: ${{ inputs.msystem == '' && inputs.build-type == 'Debug' }} shell: pwsh From 6ab1a246cb63e3d2e9c177f63c16eef000a29754 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 3 Aug 2025 12:07:57 +0100 Subject: [PATCH 078/118] Use radio buttons for Instance Renaming Mode Signed-off-by: TheKodeToad --- launcher/ui/pages/global/LauncherPage.cpp | 39 ++---- launcher/ui/pages/global/LauncherPage.ui | 137 ++++++++++++++-------- 2 files changed, 98 insertions(+), 78 deletions(-) diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 132a2c320..7a0f11c83 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -65,15 +65,6 @@ enum InstSortMode { Sort_LastLaunch }; -enum InstRenamingMode { - // Rename metadata only. - Rename_Always, - // Ask everytime. - Rename_Ask, - // Rename physical directory too. - Rename_Never -}; - LauncherPage::LauncherPage(QWidget* parent) : QWidget(parent), ui(new Ui::LauncherPage) { ui->setupUi(this); @@ -242,18 +233,12 @@ void LauncherPage::applySettings() break; } - auto renamingMode = (InstRenamingMode)ui->renamingBehaviorComboBox->currentIndex(); - switch (renamingMode) { - case Rename_Always: - s->set("InstRenamingMode", "MetadataOnly"); - break; - case Rename_Never: - s->set("InstRenamingMode", "PhysicalDir"); - break; - case Rename_Ask: - default: - s->set("InstRenamingMode", "AskEverytime"); - break; + if (ui->askToRenameDirBtn->isChecked()) { + s->set("InstRenamingMode", "AskEverytime"); + } else if (ui->alwaysRenameDirBtn->isChecked()) { + s->set("InstRenamingMode", "PhysicalDir"); + } else if (ui->neverRenameDirBtn->isChecked()) { + s->set("InstRenamingMode", "MetadataOnly"); } // Mods @@ -300,15 +285,9 @@ void LauncherPage::loadSettings() } QString renamingMode = s->get("InstRenamingMode").toString(); - InstRenamingMode renamingModeEnum; - if (renamingMode == "MetadataOnly") { - renamingModeEnum = Rename_Always; - } else if (renamingMode == "PhysicalDir") { - renamingModeEnum = Rename_Never; - } else { - renamingModeEnum = Rename_Ask; - } - ui->renamingBehaviorComboBox->setCurrentIndex(renamingModeEnum); + ui->askToRenameDirBtn->setChecked(renamingMode == "AskEverytime"); + ui->alwaysRenameDirBtn->setChecked(renamingMode == "PhysicalDir"); + ui->neverRenameDirBtn->setChecked(renamingMode == "MetadataOnly"); // Mods ui->metadataEnableBtn->setChecked(!s->get("ModMetadataDisabled").toBool()); diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 55478e6a0..c04d904cf 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -32,7 +32,7 @@ - Qt::ScrollBarAsNeeded + Qt::ScrollBarPolicy::ScrollBarAsNeeded true @@ -41,9 +41,9 @@ 0 - -356 - 742 - 1148 + 0 + 746 + 1202 @@ -64,32 +64,56 @@ - - - By &name + + + - - sortingModeGroup - - - - - - - &By last launched + + true - - sortingModeGroup - + + + 0 + + + 0 + + + 0 + + + 0 + + + + + By &name + + + sortingModeGroup + + + + + + + &By last launched + + + sortingModeGroup + + + + - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::Fixed + QSizePolicy::Policy::Fixed @@ -107,37 +131,57 @@
- - - - 0 - 0 - + + + - - - Ask what to do with the folder + + true + + + + 0 - - - - Always rename the folder + + 0 - - - - Never rename the folder—only the displayed name + + 0 - + + 0 + + + + + Ask what to do + + + + + + + Always rename the folder + + + + + + + Never rename the folder + + + + - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::Fixed + QSizePolicy::Policy::Fixed @@ -206,7 +250,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -433,7 +477,7 @@ - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter @@ -602,7 +646,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -618,7 +662,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -636,9 +680,6 @@ scrollArea - sortByNameBtn - sortLastLaunchedBtn - renamingBehaviorComboBox preferMenuBarCheckBox autoUpdateCheckBox updateIntervalSpinBox From 99f6a02a141f702048c9faee1b4c297f871149ae Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 3 Aug 2025 12:14:03 +0100 Subject: [PATCH 079/118] Cat Fit -> Cat Scaling Signed-off-by: TheKodeToad --- launcher/ui/widgets/AppearanceWidget.ui | 94 ++++++++++++------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/launcher/ui/widgets/AppearanceWidget.ui b/launcher/ui/widgets/AppearanceWidget.ui index 99bf4a500..cfe464dd6 100644 --- a/launcher/ui/widgets/AppearanceWidget.ui +++ b/launcher/ui/widgets/AppearanceWidget.ui @@ -203,53 +203,6 @@ - - - - - 0 - 0 - - - - Fit - - - - - - - - 0 - 0 - - - - - 77 - 30 - - - - 0 - - - - Fit - - - - - Fill - - - - - Stretch - - - - @@ -370,6 +323,53 @@ + + + + + 0 + 0 + + + + Cat Scaling + + + + + + + + 0 + 0 + + + + + 77 + 30 + + + + 0 + + + + Fit + + + + + Fill + + + + + Stretch + + + + From 6abd7ac673ed42d70491c64225477a6e4487354d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 4 Aug 2025 10:16:26 +0100 Subject: [PATCH 080/118] Remove invisible GroupBoxes (they appear on Fusion) Signed-off-by: TheKodeToad --- launcher/ui/pages/global/LauncherPage.ui | 122 ++++++++--------------- 1 file changed, 42 insertions(+), 80 deletions(-) diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index c04d904cf..0debe3f4d 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -43,7 +43,7 @@ 0 0 746 - 1202 + 1194 @@ -64,47 +64,23 @@ - - - + + + By &name - - true + + sortingModeGroup + + + + + + + &By last launched - - - 0 - - - 0 - - - 0 - - - 0 - - - - - By &name - - - sortingModeGroup - - - - - - - &By last launched - - - sortingModeGroup - - - - + + sortingModeGroup + @@ -131,48 +107,33 @@ - - - + + + Ask what to do - - true + + renamingBehaviorGroup + + + + + + + Always rename the folder - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Ask what to do - - - - - - - Always rename the folder - - - - - - - Never rename the folder - - - - + + renamingBehaviorGroup + + + + + + + Never rename the folder + + + renamingBehaviorGroup + @@ -711,5 +672,6 @@ + From d41db5253e682b71e9cc6f87af250e4445f25c4d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 4 Aug 2025 14:02:54 +0100 Subject: [PATCH 081/118] Refactor Filter Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 1 - launcher/Filter.cpp | 37 ---------- launcher/Filter.h | 77 +++++++------------- launcher/MMCZip.cpp | 2 +- launcher/MMCZip.h | 6 +- launcher/VersionProxyModel.cpp | 6 +- launcher/VersionProxyModel.h | 6 +- launcher/ui/java/InstallJavaDialog.cpp | 4 +- launcher/ui/pages/modplatform/CustomPage.cpp | 2 +- launcher/ui/widgets/ModFilterWidget.cpp | 8 +- launcher/ui/widgets/VersionSelectWidget.cpp | 8 +- launcher/ui/widgets/VersionSelectWidget.h | 4 +- 12 files changed, 50 insertions(+), 111 deletions(-) delete mode 100644 launcher/Filter.cpp diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 194694d7f..6af7d32a2 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -56,7 +56,6 @@ set(CORE_SOURCES # String filters Filter.h - Filter.cpp # JSON parsing helpers Json.h diff --git a/launcher/Filter.cpp b/launcher/Filter.cpp deleted file mode 100644 index adeb2209e..000000000 --- a/launcher/Filter.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "Filter.h" - -ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern) {} -bool ContainsFilter::accepts(const QString& value) -{ - return value.contains(pattern); -} - -ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern) {} -bool ExactFilter::accepts(const QString& value) -{ - return value == pattern; -} - -ExactIfPresentFilter::ExactIfPresentFilter(const QString& pattern) : pattern(pattern) {} -bool ExactIfPresentFilter::accepts(const QString& value) -{ - return value.isEmpty() || value == pattern; -} - -RegexpFilter::RegexpFilter(const QString& regexp, bool invert) : invert(invert) -{ - pattern.setPattern(regexp); - pattern.optimize(); -} -bool RegexpFilter::accepts(const QString& value) -{ - auto match = pattern.match(value); - bool matched = match.hasMatch(); - return invert ? (!matched) : (matched); -} - -ExactListFilter::ExactListFilter(const QStringList& pattern) : m_pattern(pattern) {} -bool ExactListFilter::accepts(const QString& value) -{ - return m_pattern.isEmpty() || m_pattern.contains(value); -} \ No newline at end of file diff --git a/launcher/Filter.h b/launcher/Filter.h index ae835e724..d94a45fea 100644 --- a/launcher/Filter.h +++ b/launcher/Filter.h @@ -3,59 +3,36 @@ #include #include -class Filter { - public: - virtual ~Filter() = default; - virtual bool accepts(const QString& value) = 0; -}; +using Filter = std::function; -class ContainsFilter : public Filter { - public: - ContainsFilter(const QString& pattern); - virtual ~ContainsFilter() = default; - bool accepts(const QString& value) override; +namespace Filters { +inline Filter inverse(Filter filter) +{ + return [filter = std::move(filter)](const QString& src) { return !filter(src); }; +} - private: - QString pattern; -}; +inline Filter contains(QString pattern) +{ + return [pattern = std::move(pattern)](const QString& src) { return src.contains(pattern); }; +} -class ExactFilter : public Filter { - public: - ExactFilter(const QString& pattern); - virtual ~ExactFilter() = default; - bool accepts(const QString& value) override; +inline Filter equals(QString pattern) +{ + return [pattern = std::move(pattern)](const QString& src) { return src == pattern; }; +} - private: - QString pattern; -}; +inline Filter equalsAny(QStringList patterns = {}) +{ + return [patterns = std::move(patterns)](const QString& src) { return patterns.isEmpty() || patterns.contains(src); }; +} -class ExactIfPresentFilter : public Filter { - public: - ExactIfPresentFilter(const QString& pattern); - virtual ~ExactIfPresentFilter() override = default; - bool accepts(const QString& value) override; +inline Filter equalsOrEmpty(QString pattern) +{ + return [pattern = std::move(pattern)](const QString& src) { return src.isEmpty() || src == pattern; }; +} - private: - QString pattern; -}; - -class RegexpFilter : public Filter { - public: - RegexpFilter(const QString& regexp, bool invert); - virtual ~RegexpFilter() = default; - bool accepts(const QString& value) override; - - private: - QRegularExpression pattern; - bool invert = false; -}; - -class ExactListFilter : public Filter { - public: - ExactListFilter(const QStringList& pattern = {}); - virtual ~ExactListFilter() = default; - bool accepts(const QString& value) override; - - private: - QStringList m_pattern; -}; +inline Filter regexp(QRegularExpression pattern) +{ + return [pattern = std::move(pattern)](const QString& src) { return pattern.match(src).hasMatch(); }; +} +} // namespace Filters diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 0b1a2b39e..dfe397930 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -51,7 +51,7 @@ namespace MMCZip { // ours -bool mergeZipFiles(QuaZip* into, QFileInfo from, QSet& contained, const FilterFunction& filter) +bool mergeZipFiles(QuaZip* into, QFileInfo from, QSet& contained, const Filter& filter) { QuaZip modZip(from.filePath()); modZip.open(QuaZip::mdUnzip); diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index fe0c79de2..aafcbd194 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -52,16 +52,16 @@ #if defined(LAUNCHER_APPLICATION) #include "minecraft/mod/Mod.h" #endif +#include "Filter.h" #include "tasks/Task.h" namespace MMCZip { -using FilterFunction = std::function; using FilterFileFunction = std::function; /** * Merge two zip files, using a filter function */ -bool mergeZipFiles(QuaZip* into, QFileInfo from, QSet& contained, const FilterFunction& filter = nullptr); +bool mergeZipFiles(QuaZip* into, QFileInfo from, QSet& contained, const Filter& filter = nullptr); /** * Compress directory, by providing a list of files to compress @@ -178,7 +178,7 @@ class ExportToZipTask : public Task { QString destinationPrefix = "", bool followSymlinks = false, bool utf8Enabled = false) - : ExportToZipTask(outputPath, QDir(dir), files, destinationPrefix, followSymlinks, utf8Enabled) {}; + : ExportToZipTask(outputPath, QDir(dir), files, destinationPrefix, followSymlinks, utf8Enabled){}; virtual ~ExportToZipTask() = default; diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 165dd4cb7..950b2276a 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -63,7 +63,7 @@ class VersionFilterModel : public QSortFilterProxyModel { for (auto it = filters.begin(); it != filters.end(); ++it) { auto data = sourceModel()->data(idx, it.key()); auto match = data.toString(); - if (!it.value()->accepts(match)) { + if (!it.value()(match)) { return false; } } @@ -380,9 +380,9 @@ void VersionProxyModel::clearFilters() filterModel->filterChanged(); } -void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filter* f) +void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filter f) { - m_filters[column].reset(f); + m_filters[column] = std::move(f); filterModel->filterChanged(); } diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index 7965af0ad..0fcb380e4 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -10,11 +10,11 @@ class VersionProxyModel : public QAbstractProxyModel { Q_OBJECT public: enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName, JavaMajor }; - using FilterMap = QHash>; + using FilterMap = QHash; public: VersionProxyModel(QObject* parent = 0); - virtual ~VersionProxyModel() {}; + virtual ~VersionProxyModel(){}; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; @@ -28,7 +28,7 @@ class VersionProxyModel : public QAbstractProxyModel { const FilterMap& filters() const; const QString& search() const; - void setFilter(BaseVersionList::ModelRoles column, Filter* filter); + void setFilter(BaseVersionList::ModelRoles column, Filter filter); void setSearch(const QString& search); void clearFilters(); QModelIndex getRecommended() const; diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index 5f69b9d46..4a628b003 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -140,9 +140,9 @@ class InstallJavaPage : public QWidget, public BasePage { void recommendedFilterChanged() { if (m_recommend) { - majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, new ExactListFilter(m_recommended_majors)); + majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, Filters::equalsAny(m_recommended_majors)); } else { - majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, new ExactListFilter()); + majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, Filters::equalsAny()); } } diff --git a/launcher/ui/pages/modplatform/CustomPage.cpp b/launcher/ui/pages/modplatform/CustomPage.cpp index ba22bd2e6..87e126fd7 100644 --- a/launcher/ui/pages/modplatform/CustomPage.cpp +++ b/launcher/ui/pages/modplatform/CustomPage.cpp @@ -104,7 +104,7 @@ void CustomPage::filterChanged() if (ui->experimentsFilter->isChecked()) out << "(experiment)"; auto regexp = out.join('|'); - ui->versionList->setFilter(BaseVersionList::TypeRole, new RegexpFilter(regexp, false)); + ui->versionList->setFilter(BaseVersionList::TypeRole, Filters::regexp(QRegularExpression(regexp))); } void CustomPage::loaderFilterChanged() diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index 654eb75b1..522829fe0 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -114,7 +114,7 @@ ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, bool extended) ui->setupUi(this); m_versions_proxy = new VersionProxyModel(this); - m_versions_proxy->setFilter(BaseVersionList::TypeRole, new ExactFilter("release")); + m_versions_proxy->setFilter(BaseVersionList::TypeRole, Filters::equals("release")); QAbstractProxyModel* proxy = new VersionBasicModel(this); proxy->setSourceModel(m_versions_proxy); @@ -152,9 +152,9 @@ ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, bool extended) connect(ui->liteLoader, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); connect(ui->babric, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); connect(ui->btaBabric, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); - + connect(ui->showMoreButton, &QPushButton::clicked, this, &ModFilterWidget::onShowMoreClicked); - + if (!extended) { ui->showMoreButton->setVisible(false); ui->extendedModLoadersWidget->setVisible(false); @@ -253,7 +253,7 @@ void ModFilterWidget::onShowAllVersionsChanged() if (ui->showAllVersions->isChecked()) m_versions_proxy->clearFilters(); else - m_versions_proxy->setFilter(BaseVersionList::TypeRole, new ExactFilter("release")); + m_versions_proxy->setFilter(BaseVersionList::TypeRole, Filters::equals("release")); } void ModFilterWidget::onVersionFilterChanged(int) diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index 2d735d18f..040355f4b 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -224,20 +224,20 @@ BaseVersion::Ptr VersionSelectWidget::selectedVersion() const void VersionSelectWidget::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) { - m_proxyModel->setFilter(role, new ContainsFilter(filter)); + m_proxyModel->setFilter(role, Filters::contains(filter)); } void VersionSelectWidget::setExactFilter(BaseVersionList::ModelRoles role, QString filter) { - m_proxyModel->setFilter(role, new ExactFilter(filter)); + m_proxyModel->setFilter(role, Filters::equals(filter)); } void VersionSelectWidget::setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter) { - m_proxyModel->setFilter(role, new ExactIfPresentFilter(filter)); + m_proxyModel->setFilter(role, Filters::equalsOrEmpty(filter)); } -void VersionSelectWidget::setFilter(BaseVersionList::ModelRoles role, Filter* filter) +void VersionSelectWidget::setFilter(BaseVersionList::ModelRoles role, Filter filter) { m_proxyModel->setFilter(role, filter); } diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index c16d4c0dd..c66d7e98e 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -39,13 +39,13 @@ #include #include #include "BaseVersionList.h" +#include "Filter.h" #include "VersionListView.h" class VersionProxyModel; class VersionListView; class QVBoxLayout; class QProgressBar; -class Filter; class VersionSelectWidget : public QWidget { Q_OBJECT @@ -70,7 +70,7 @@ class VersionSelectWidget : public QWidget { void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); void setExactFilter(BaseVersionList::ModelRoles role, QString filter); void setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter); - void setFilter(BaseVersionList::ModelRoles role, Filter* filter); + void setFilter(BaseVersionList::ModelRoles role, Filter filter); void setEmptyString(QString emptyString); void setEmptyErrorString(QString emptyErrorString); void setEmptyMode(VersionListView::EmptyMode mode); From d7eddd37739ec507786e8399b20d9c6b750a3add Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 4 Aug 2025 14:28:45 +0100 Subject: [PATCH 082/118] Replace IPathMatcher stuff with Filter Signed-off-by: TheKodeToad --- launcher/Application.cpp | 31 ++++++++--------- launcher/BaseInstance.h | 1 - launcher/CMakeLists.txt | 10 ------ launcher/DataMigrationTask.cpp | 2 +- launcher/DataMigrationTask.h | 6 ++-- launcher/FileSystem.cpp | 6 ++-- launcher/FileSystem.h | 20 +++++------ launcher/Filter.h | 20 +++++++++-- launcher/InstanceCopyTask.cpp | 7 ++-- launcher/InstanceCopyTask.h | 3 +- launcher/MMCZip.h | 2 +- launcher/RecursiveFileSystemWatcher.cpp | 2 +- launcher/RecursiveFileSystemWatcher.h | 6 ++-- launcher/VersionProxyModel.h | 2 +- launcher/minecraft/MinecraftInstance.cpp | 1 - launcher/pathmatcher/FSTreeMatcher.h | 14 -------- launcher/pathmatcher/IPathMatcher.h | 12 ------- launcher/pathmatcher/MultiMatcher.h | 27 --------------- launcher/pathmatcher/RegexpMatcher.h | 40 ---------------------- launcher/pathmatcher/SimplePrefixMatcher.h | 24 ------------- launcher/ui/pages/instance/OtherLogsPage.h | 1 - tests/FileSystem_test.cpp | 12 +++---- 22 files changed, 66 insertions(+), 183 deletions(-) delete mode 100644 launcher/pathmatcher/FSTreeMatcher.h delete mode 100644 launcher/pathmatcher/IPathMatcher.h delete mode 100644 launcher/pathmatcher/MultiMatcher.h delete mode 100644 launcher/pathmatcher/RegexpMatcher.h delete mode 100644 launcher/pathmatcher/SimplePrefixMatcher.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index d7182c48d..a8bfd52e3 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -46,8 +46,6 @@ #include "DataMigrationTask.h" #include "java/JavaInstallList.h" #include "net/PasteUpload.h" -#include "pathmatcher/MultiMatcher.h" -#include "pathmatcher/SimplePrefixMatcher.h" #include "tasks/Task.h" #include "tools/GenericProfiler.h" #include "ui/InstanceWindow.h" @@ -1985,22 +1983,23 @@ bool Application::handleDataMigration(const QString& currentData, if (!currentExists) { // Migrate! - auto matcher = std::make_shared(); - matcher->add(std::make_shared(configFile)); - matcher->add(std::make_shared( - BuildConfig.LAUNCHER_CONFIGFILE)); // it's possible that we already used that directory before - matcher->add(std::make_shared("logs/")); - matcher->add(std::make_shared("accounts.json")); - matcher->add(std::make_shared("accounts/")); - matcher->add(std::make_shared("assets/")); - matcher->add(std::make_shared("icons/")); - matcher->add(std::make_shared("instances/")); - matcher->add(std::make_shared("libraries/")); - matcher->add(std::make_shared("mods/")); - matcher->add(std::make_shared("themes/")); + using namespace Filters; + + QList filters; + filters.append(equals(configFile)); + filters.append(equals(BuildConfig.LAUNCHER_CONFIGFILE)); // it's possible that we already used that directory before + filters.append(startsWith("logs/")); + filters.append(equals("accounts.json")); + filters.append(startsWith("accounts/")); + filters.append(startsWith("assets/")); + filters.append(startsWith("icons/")); + filters.append(startsWith("instances/")); + filters.append(startsWith("libraries/")); + filters.append(startsWith("mods/")); + filters.append(startsWith("themes/")); ProgressDialog diag; - DataMigrationTask task(oldData, currentData, matcher); + DataMigrationTask task(oldData, currentData, any(std::move(filters))); if (diag.execWithTask(&task)) { qDebug() << "<> Migration succeeded"; setDoNotMigrate(); diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h index 6baac4ce8..a542b76eb 100644 --- a/launcher/BaseInstance.h +++ b/launcher/BaseInstance.h @@ -52,7 +52,6 @@ #include "BaseVersionList.h" #include "MessageLevel.h" #include "minecraft/auth/MinecraftAccount.h" -#include "pathmatcher/IPathMatcher.h" #include "settings/INIFile.h" #include "net/Mode.h" diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 6af7d32a2..2d1c62269 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -107,15 +107,6 @@ if (UNIX AND NOT CYGWIN AND NOT APPLE) ) endif() -set(PATHMATCHER_SOURCES - # Path matchers - pathmatcher/FSTreeMatcher.h - pathmatcher/IPathMatcher.h - pathmatcher/MultiMatcher.h - pathmatcher/RegexpMatcher.h - pathmatcher/SimplePrefixMatcher.h -) - set(NET_SOURCES # network stuffs net/ByteArraySink.h @@ -759,7 +750,6 @@ endif() set(LOGIC_SOURCES ${CORE_SOURCES} - ${PATHMATCHER_SOURCES} ${NET_SOURCES} ${LAUNCH_SOURCES} ${UPDATE_SOURCES} diff --git a/launcher/DataMigrationTask.cpp b/launcher/DataMigrationTask.cpp index 18decc7c3..9677f868e 100644 --- a/launcher/DataMigrationTask.cpp +++ b/launcher/DataMigrationTask.cpp @@ -12,7 +12,7 @@ #include -DataMigrationTask::DataMigrationTask(const QString& sourcePath, const QString& targetPath, const IPathMatcher::Ptr pathMatcher) +DataMigrationTask::DataMigrationTask(const QString& sourcePath, const QString& targetPath, Filter pathMatcher) : Task(), m_sourcePath(sourcePath), m_targetPath(targetPath), m_pathMatcher(pathMatcher), m_copy(sourcePath, targetPath) { m_copy.matcher(m_pathMatcher).whitelist(true); diff --git a/launcher/DataMigrationTask.h b/launcher/DataMigrationTask.h index fc613cd5e..9a2b0adb8 100644 --- a/launcher/DataMigrationTask.h +++ b/launcher/DataMigrationTask.h @@ -5,7 +5,7 @@ #pragma once #include "FileSystem.h" -#include "pathmatcher/IPathMatcher.h" +#include "Filter.h" #include "tasks/Task.h" #include @@ -18,7 +18,7 @@ class DataMigrationTask : public Task { Q_OBJECT public: - explicit DataMigrationTask(const QString& sourcePath, const QString& targetPath, IPathMatcher::Ptr pathmatcher); + explicit DataMigrationTask(const QString& sourcePath, const QString& targetPath, Filter pathmatcher); ~DataMigrationTask() override = default; protected: @@ -33,7 +33,7 @@ class DataMigrationTask : public Task { private: const QString& m_sourcePath; const QString& m_targetPath; - const IPathMatcher::Ptr m_pathMatcher; + const Filter m_pathMatcher; FS::copy m_copy; int m_toCopy = 0; diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 308f8620e..e987fa59a 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -331,7 +331,7 @@ bool copy::operator()(const QString& offset, bool dryRun) // Function that'll do the actual copying auto copy_file = [this, dryRun, src, dst, opt, &err](QString src_path, QString relative_dst_path) { - if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist)) + if (m_matcher && (m_matcher(relative_dst_path) != m_whitelist)) return; auto dst_path = PathCombine(dst, relative_dst_path); @@ -418,7 +418,7 @@ void create_link::make_link_list(const QString& offset) // Function that'll do the actual linking auto link_file = [this, dst](QString src_path, QString relative_dst_path) { - if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist)) { + if (m_matcher && (m_matcher(relative_dst_path) != m_whitelist)) { qDebug() << "path" << relative_dst_path << "in black list or not in whitelist"; return; } @@ -1277,7 +1277,7 @@ bool clone::operator()(const QString& offset, bool dryRun) // Function that'll do the actual cloneing auto cloneFile = [this, dryRun, dst, &err](QString src_path, QString relative_dst_path) { - if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist)) + if (m_matcher && (m_matcher(relative_dst_path) != m_whitelist)) return; auto dst_path = PathCombine(dst, relative_dst_path); diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index 0e573a09e..b0d9ae2e8 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -38,7 +38,7 @@ #pragma once #include "Exception.h" -#include "pathmatcher/IPathMatcher.h" +#include "Filter.h" #include @@ -115,9 +115,9 @@ class copy : public QObject { m_followSymlinks = follow; return *this; } - copy& matcher(IPathMatcher::Ptr filter) + copy& matcher(Filter filter) { - m_matcher = filter; + m_matcher = std::move(filter); return *this; } copy& whitelist(bool whitelist) @@ -147,7 +147,7 @@ class copy : public QObject { private: bool m_followSymlinks = true; - IPathMatcher::Ptr m_matcher = nullptr; + Filter m_matcher = nullptr; bool m_whitelist = false; bool m_overwrite = false; QDir m_src; @@ -209,9 +209,9 @@ class create_link : public QObject { m_useHardLinks = useHard; return *this; } - create_link& matcher(IPathMatcher::Ptr filter) + create_link& matcher(Filter filter) { - m_matcher = filter; + m_matcher = std::move(filter); return *this; } create_link& whitelist(bool whitelist) @@ -260,7 +260,7 @@ class create_link : public QObject { private: bool m_useHardLinks = false; - IPathMatcher::Ptr m_matcher = nullptr; + Filter m_matcher = nullptr; bool m_whitelist = false; bool m_recursive = true; @@ -492,9 +492,9 @@ class clone : public QObject { m_src.setPath(src); m_dst.setPath(dst); } - clone& matcher(IPathMatcher::Ptr filter) + clone& matcher(Filter filter) { - m_matcher = filter; + m_matcher = std::move(filter); return *this; } clone& whitelist(bool whitelist) @@ -518,7 +518,7 @@ class clone : public QObject { bool operator()(const QString& offset, bool dryRun = false); private: - IPathMatcher::Ptr m_matcher = nullptr; + Filter m_matcher = nullptr; bool m_whitelist = false; QDir m_src; QDir m_dst; diff --git a/launcher/Filter.h b/launcher/Filter.h index d94a45fea..317f5b067 100644 --- a/launcher/Filter.h +++ b/launcher/Filter.h @@ -11,9 +11,15 @@ inline Filter inverse(Filter filter) return [filter = std::move(filter)](const QString& src) { return !filter(src); }; } -inline Filter contains(QString pattern) +inline Filter any(QList filters) { - return [pattern = std::move(pattern)](const QString& src) { return src.contains(pattern); }; + return [filters = std::move(filters)](const QString& src) { + for (auto& filter : filters) + if (filter(src)) + return true; + + return false; + }; } inline Filter equals(QString pattern) @@ -31,6 +37,16 @@ inline Filter equalsOrEmpty(QString pattern) return [pattern = std::move(pattern)](const QString& src) { return src.isEmpty() || src == pattern; }; } +inline Filter contains(QString pattern) +{ + return [pattern = std::move(pattern)](const QString& src) { return src.contains(pattern); }; +} + +inline Filter startsWith(QString pattern) +{ + return [pattern = std::move(pattern)](const QString& src) { return src.startsWith(pattern); }; +} + inline Filter regexp(QRegularExpression pattern) { return [pattern = std::move(pattern)](const QString& src) { return pattern.match(src).hasMatch(); }; diff --git a/launcher/InstanceCopyTask.cpp b/launcher/InstanceCopyTask.cpp index fb5963532..eba1a1339 100644 --- a/launcher/InstanceCopyTask.cpp +++ b/launcher/InstanceCopyTask.cpp @@ -3,8 +3,8 @@ #include #include #include "FileSystem.h" +#include "Filter.h" #include "NullInstance.h" -#include "pathmatcher/RegexpMatcher.h" #include "settings/INISettingsObject.h" #include "tasks/Task.h" @@ -30,9 +30,8 @@ InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, const InstanceCopyP if (!filters.isEmpty()) { // Set regex filter: // FIXME: get this from the original instance type... - auto matcherReal = new RegexpMatcher(filters); - matcherReal->caseSensitive(false); - m_matcher.reset(matcherReal); + QRegularExpression regexp(filters, QRegularExpression::CaseInsensitiveOption); + m_matcher = Filters::regexp(regexp); } } diff --git a/launcher/InstanceCopyTask.h b/launcher/InstanceCopyTask.h index 3aba13e5c..ef4120bc6 100644 --- a/launcher/InstanceCopyTask.h +++ b/launcher/InstanceCopyTask.h @@ -5,6 +5,7 @@ #include #include "BaseInstance.h" #include "BaseVersion.h" +#include "Filter.h" #include "InstanceCopyPrefs.h" #include "InstanceTask.h" #include "net/NetJob.h" @@ -28,7 +29,7 @@ class InstanceCopyTask : public InstanceTask { InstancePtr m_origInstance; QFuture m_copyFuture; QFutureWatcher m_copyFutureWatcher; - IPathMatcher::Ptr m_matcher; + Filter m_matcher; bool m_keepPlaytime; bool m_useLinks = false; bool m_useHardLinks = false; diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index aafcbd194..e23d29d65 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -178,7 +178,7 @@ class ExportToZipTask : public Task { QString destinationPrefix = "", bool followSymlinks = false, bool utf8Enabled = false) - : ExportToZipTask(outputPath, QDir(dir), files, destinationPrefix, followSymlinks, utf8Enabled){}; + : ExportToZipTask(outputPath, QDir(dir), files, destinationPrefix, followSymlinks, utf8Enabled) {}; virtual ~ExportToZipTask() = default; diff --git a/launcher/RecursiveFileSystemWatcher.cpp b/launcher/RecursiveFileSystemWatcher.cpp index 5cb3cd0be..b0137fb5c 100644 --- a/launcher/RecursiveFileSystemWatcher.cpp +++ b/launcher/RecursiveFileSystemWatcher.cpp @@ -78,7 +78,7 @@ QStringList RecursiveFileSystemWatcher::scanRecursive(const QDir& directory) } for (const QString& file : directory.entryList(QDir::Files | QDir::Hidden)) { auto relPath = m_root.relativeFilePath(directory.absoluteFilePath(file)); - if (m_matcher->matches(relPath)) { + if (m_matcher(relPath)) { ret.append(relPath); } } diff --git a/launcher/RecursiveFileSystemWatcher.h b/launcher/RecursiveFileSystemWatcher.h index 7f96f5cd0..0a71e64c2 100644 --- a/launcher/RecursiveFileSystemWatcher.h +++ b/launcher/RecursiveFileSystemWatcher.h @@ -2,7 +2,7 @@ #include #include -#include "pathmatcher/IPathMatcher.h" +#include "Filter.h" class RecursiveFileSystemWatcher : public QObject { Q_OBJECT @@ -16,7 +16,7 @@ class RecursiveFileSystemWatcher : public QObject { void setWatchFiles(bool watchFiles); bool watchFiles() const { return m_watchFiles; } - void setMatcher(IPathMatcher::Ptr matcher) { m_matcher = matcher; } + void setMatcher(Filter matcher) { m_matcher = std::move(matcher); } QStringList files() const { return m_files; } @@ -32,7 +32,7 @@ class RecursiveFileSystemWatcher : public QObject { QDir m_root; bool m_watchFiles = false; bool m_isEnabled = false; - IPathMatcher::Ptr m_matcher; + Filter m_matcher; QFileSystemWatcher* m_watcher; diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index 0fcb380e4..ddd5d2458 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -14,7 +14,7 @@ class VersionProxyModel : public QAbstractProxyModel { public: VersionProxyModel(QObject* parent = 0); - virtual ~VersionProxyModel(){}; + virtual ~VersionProxyModel() {}; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 7749d0f6b..a58ad21bc 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -53,7 +53,6 @@ #include "FileSystem.h" #include "MMCTime.h" #include "java/JavaVersion.h" -#include "pathmatcher/MultiMatcher.h" #include "launch/LaunchTask.h" #include "launch/TaskStepWrapper.h" diff --git a/launcher/pathmatcher/FSTreeMatcher.h b/launcher/pathmatcher/FSTreeMatcher.h deleted file mode 100644 index d8d36d2c3..000000000 --- a/launcher/pathmatcher/FSTreeMatcher.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include "IPathMatcher.h" - -class FSTreeMatcher : public IPathMatcher { - public: - virtual ~FSTreeMatcher() {}; - FSTreeMatcher(SeparatorPrefixTree<'/'>& tree) : m_fsTree(tree) {} - - bool matches(const QString& string) const override { return m_fsTree.covers(string); } - - SeparatorPrefixTree<'/'>& m_fsTree; -}; diff --git a/launcher/pathmatcher/IPathMatcher.h b/launcher/pathmatcher/IPathMatcher.h deleted file mode 100644 index f3b01e8cf..000000000 --- a/launcher/pathmatcher/IPathMatcher.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include -#include - -class IPathMatcher { - public: - using Ptr = std::shared_ptr; - - public: - virtual ~IPathMatcher() {} - virtual bool matches(const QString& string) const = 0; -}; diff --git a/launcher/pathmatcher/MultiMatcher.h b/launcher/pathmatcher/MultiMatcher.h deleted file mode 100644 index 3ad07b643..000000000 --- a/launcher/pathmatcher/MultiMatcher.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include "IPathMatcher.h" - -class MultiMatcher : public IPathMatcher { - public: - virtual ~MultiMatcher() {}; - MultiMatcher() {} - MultiMatcher& add(Ptr add) - { - m_matchers.append(add); - return *this; - } - - virtual bool matches(const QString& string) const override - { - for (auto iter : m_matchers) { - if (iter->matches(string)) { - return true; - } - } - return false; - } - - QList m_matchers; -}; diff --git a/launcher/pathmatcher/RegexpMatcher.h b/launcher/pathmatcher/RegexpMatcher.h deleted file mode 100644 index e36516386..000000000 --- a/launcher/pathmatcher/RegexpMatcher.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include "IPathMatcher.h" - -class RegexpMatcher : public IPathMatcher { - public: - virtual ~RegexpMatcher() {} - RegexpMatcher(const QString& regexp) - { - m_regexp.setPattern(regexp); - m_onlyFilenamePart = !regexp.contains('/'); - } - - RegexpMatcher(const QRegularExpression& regex) : m_regexp(regex) { m_onlyFilenamePart = !regex.pattern().contains('/'); } - - RegexpMatcher& caseSensitive(bool cs = true) - { - if (cs) { - m_regexp.setPatternOptions(QRegularExpression::CaseInsensitiveOption); - } else { - m_regexp.setPatternOptions(QRegularExpression::NoPatternOption); - } - return *this; - } - - virtual bool matches(const QString& string) const override - { - if (m_onlyFilenamePart) { - auto slash = string.lastIndexOf('/'); - if (slash != -1) { - auto part = string.mid(slash + 1); - return m_regexp.match(part).hasMatch(); - } - } - return m_regexp.match(string).hasMatch(); - } - QRegularExpression m_regexp; - bool m_onlyFilenamePart = false; -}; diff --git a/launcher/pathmatcher/SimplePrefixMatcher.h b/launcher/pathmatcher/SimplePrefixMatcher.h deleted file mode 100644 index 57bf63a30..000000000 --- a/launcher/pathmatcher/SimplePrefixMatcher.h +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu -// -// SPDX-License-Identifier: GPL-3.0-only - -#include "IPathMatcher.h" - -class SimplePrefixMatcher : public IPathMatcher { - public: - virtual ~SimplePrefixMatcher() {}; - SimplePrefixMatcher(const QString& prefix) - { - m_prefix = prefix; - m_isPrefix = prefix.endsWith('/'); - } - - virtual bool matches(const QString& string) const override - { - if (m_isPrefix) - return string.startsWith(m_prefix); - return string == m_prefix; - } - QString m_prefix; - bool m_isPrefix = false; -}; diff --git a/launcher/ui/pages/instance/OtherLogsPage.h b/launcher/ui/pages/instance/OtherLogsPage.h index 4104d8f3c..fbf9991e1 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.h +++ b/launcher/ui/pages/instance/OtherLogsPage.h @@ -38,7 +38,6 @@ #include #include -#include #include #include "LogPage.h" #include "ui/pages/BasePage.h" diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index 48da30a25..9e99a3f30 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -12,8 +12,6 @@ #include namespace fs = std::filesystem; -#include - class LinkTask : public Task { Q_OBJECT @@ -27,7 +25,7 @@ class LinkTask : public Task { ~LinkTask() { delete m_lnk; } - void matcher(IPathMatcher::Ptr filter) { m_lnk->matcher(filter); } + void matcher(Filter filter) { m_lnk->matcher(filter); } void linkRecursively(bool recursive) { @@ -190,7 +188,7 @@ class FileSystemTest : public QObject { qDebug() << tempDir.path(); qDebug() << target_dir.path(); FS::copy c(folder, target_dir.path()); - RegexpMatcher::Ptr re = std::make_shared("[.]?mcmeta"); + auto re = Filters::regexp(QRegularExpression("/[.]?mcmeta$")); c.matcher(re); c(); @@ -223,7 +221,7 @@ class FileSystemTest : public QObject { qDebug() << tempDir.path(); qDebug() << target_dir.path(); FS::copy c(folder, target_dir.path()); - RegexpMatcher::Ptr re = std::make_shared("[.]?mcmeta"); + auto re = Filters::regexp(QRegularExpression("/[.]?mcmeta$")); c.matcher(re); c.whitelist(true); c(); @@ -415,7 +413,7 @@ class FileSystemTest : public QObject { qDebug() << target_dir.path(); LinkTask lnk_tsk(folder, target_dir.path()); - RegexpMatcher::Ptr re = std::make_shared("[.]?mcmeta"); + auto re = Filters::regexp(QRegularExpression("/[.]?mcmeta$")); lnk_tsk.matcher(re); lnk_tsk.linkRecursively(true); connect(&lnk_tsk, &Task::finished, @@ -461,7 +459,7 @@ class FileSystemTest : public QObject { qDebug() << target_dir.path(); LinkTask lnk_tsk(folder, target_dir.path()); - RegexpMatcher::Ptr re = std::make_shared("[.]?mcmeta"); + auto re = Filters::regexp(QRegularExpression("/[.]?mcmeta$")); lnk_tsk.matcher(re); lnk_tsk.linkRecursively(true); lnk_tsk.whitelist(true); From e14b18ca71d3e24c60331829c78a2b4a57a6f5ec Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 4 Aug 2025 15:31:38 +0100 Subject: [PATCH 083/118] Fix tests (oops) Signed-off-by: TheKodeToad --- tests/FileSystem_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index 9e99a3f30..37e5e1201 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -188,7 +188,7 @@ class FileSystemTest : public QObject { qDebug() << tempDir.path(); qDebug() << target_dir.path(); FS::copy c(folder, target_dir.path()); - auto re = Filters::regexp(QRegularExpression("/[.]?mcmeta$")); + auto re = Filters::regexp(QRegularExpression("[.]?mcmeta")); c.matcher(re); c(); @@ -221,7 +221,7 @@ class FileSystemTest : public QObject { qDebug() << tempDir.path(); qDebug() << target_dir.path(); FS::copy c(folder, target_dir.path()); - auto re = Filters::regexp(QRegularExpression("/[.]?mcmeta$")); + auto re = Filters::regexp(QRegularExpression("[.]?mcmeta")); c.matcher(re); c.whitelist(true); c(); @@ -413,7 +413,7 @@ class FileSystemTest : public QObject { qDebug() << target_dir.path(); LinkTask lnk_tsk(folder, target_dir.path()); - auto re = Filters::regexp(QRegularExpression("/[.]?mcmeta$")); + auto re = Filters::regexp(QRegularExpression("[.]?mcmeta")); lnk_tsk.matcher(re); lnk_tsk.linkRecursively(true); connect(&lnk_tsk, &Task::finished, @@ -459,7 +459,7 @@ class FileSystemTest : public QObject { qDebug() << target_dir.path(); LinkTask lnk_tsk(folder, target_dir.path()); - auto re = Filters::regexp(QRegularExpression("/[.]?mcmeta$")); + auto re = Filters::regexp(QRegularExpression("[.]?mcmeta")); lnk_tsk.matcher(re); lnk_tsk.linkRecursively(true); lnk_tsk.whitelist(true); From 3ba948301119a3e760689d6f6b60d81947667ffb Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 4 Aug 2025 13:29:19 +0100 Subject: [PATCH 084/118] Simplify Rule Signed-off-by: TheKodeToad --- launcher/minecraft/Library.cpp | 8 +- launcher/minecraft/Library.h | 4 +- launcher/minecraft/MojangVersionFormat.cpp | 8 +- launcher/minecraft/Rule.cpp | 109 +++++++++------------ launcher/minecraft/Rule.h | 63 +++--------- 5 files changed, 73 insertions(+), 119 deletions(-) diff --git a/launcher/minecraft/Library.cpp b/launcher/minecraft/Library.cpp index 0bc462474..026f9c281 100644 --- a/launcher/minecraft/Library.cpp +++ b/launcher/minecraft/Library.cpp @@ -242,13 +242,13 @@ bool Library::isActive(const RuntimeContext& runtimeContext) const if (m_rules.empty()) { result = true; } else { - RuleAction ruleResult = Disallow; + Rule::Action ruleResult = Rule::Disallow; for (auto rule : m_rules) { - RuleAction temp = rule->apply(this, runtimeContext); - if (temp != Defer) + Rule::Action temp = rule.apply(runtimeContext); + if (temp != Rule::Defer) ruleResult = temp; } - result = result && (ruleResult == Allow); + result = result && (ruleResult == Rule::Allow); } if (isNative()) { result = result && !getCompatibleNative(runtimeContext).isNull(); diff --git a/launcher/minecraft/Library.h b/launcher/minecraft/Library.h index d3019e814..d827554aa 100644 --- a/launcher/minecraft/Library.h +++ b/launcher/minecraft/Library.h @@ -129,7 +129,7 @@ class Library { void setHint(const QString& hint) { m_hint = hint; } /// Set the load rules - void setRules(QList> rules) { m_rules = rules; } + void setRules(QList rules) { m_rules = rules; } /// Returns true if the library should be loaded (or extracted, in case of natives) bool isActive(const RuntimeContext& runtimeContext) const; @@ -203,7 +203,7 @@ class Library { bool applyRules = false; /// rules associated with the library - QList> m_rules; + QList m_rules; /// MOJANG: container with Mojang style download info MojangLibraryDownloadInfo::Ptr m_mojangDownloads; diff --git a/launcher/minecraft/MojangVersionFormat.cpp b/launcher/minecraft/MojangVersionFormat.cpp index d17a3a21f..42730b12d 100644 --- a/launcher/minecraft/MojangVersionFormat.cpp +++ b/launcher/minecraft/MojangVersionFormat.cpp @@ -319,7 +319,11 @@ LibraryPtr MojangVersionFormat::libraryFromJson(ProblemContainer& problems, cons } if (libObj.contains("rules")) { out->applyRules = true; - out->m_rules = rulesFromJsonV4(libObj); + + QJsonArray rulesArray = requireArray(libObj.value("rules")); + for (auto rule : rulesArray) { + out->m_rules.append(Rule::fromJson(requireObject(rule))); + } } if (libObj.contains("downloads")) { out->m_mojangDownloads = libDownloadInfoFromJson(libObj); @@ -355,7 +359,7 @@ QJsonObject MojangVersionFormat::libraryToJson(Library* library) if (!library->m_rules.isEmpty()) { QJsonArray allRules; for (auto& rule : library->m_rules) { - QJsonObject ruleObj = rule->toJson(); + QJsonObject ruleObj = rule.toJson(); allRules.append(ruleObj); } libRoot.insert("rules", allRules); diff --git a/launcher/minecraft/Rule.cpp b/launcher/minecraft/Rule.cpp index d80aab84d..3cc655835 100644 --- a/launcher/minecraft/Rule.cpp +++ b/launcher/minecraft/Rule.cpp @@ -2,6 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2025 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,72 +39,54 @@ #include "Rule.h" -RuleAction RuleAction_fromString(QString name) +Rule Rule::fromJson(const QJsonObject& object) { - if (name == "allow") - return Allow; - if (name == "disallow") - return Disallow; - return Defer; -} + Rule result; -QList> rulesFromJsonV4(const QJsonObject& objectWithRules) -{ - QList> rules; - auto rulesVal = objectWithRules.value("rules"); - if (!rulesVal.isArray()) - return rules; + if (object["action"] == "allow") + result.action = Allow; + else if (object["action"] == "disallow") + result.action = Disallow; - QJsonArray ruleList = rulesVal.toArray(); - for (auto ruleVal : ruleList) { - std::shared_ptr rule; - if (!ruleVal.isObject()) - continue; - auto ruleObj = ruleVal.toObject(); - auto actionVal = ruleObj.value("action"); - if (!actionVal.isString()) - continue; - auto action = RuleAction_fromString(actionVal.toString()); - if (action == Defer) - continue; - - auto osVal = ruleObj.value("os"); - if (!osVal.isObject()) { - // add a new implicit action rule - rules.append(ImplicitRule::create(action)); - continue; - } - - auto osObj = osVal.toObject(); - auto osNameVal = osObj.value("name"); - if (!osNameVal.isString()) - continue; - QString osName = osNameVal.toString(); - QString versionRegex = osObj.value("version").toString(); - // add a new OS rule - rules.append(OsRule::create(action, osName, versionRegex)); - } - return rules; -} - -QJsonObject ImplicitRule::toJson() -{ - QJsonObject ruleObj; - ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow")); - return ruleObj; -} - -QJsonObject OsRule::toJson() -{ - QJsonObject ruleObj; - ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow")); - QJsonObject osObj; - { - osObj.insert("name", m_system); - if (!m_version_regexp.isEmpty()) { - osObj.insert("version", m_version_regexp); + if (auto os = object["os"]; os.isObject()) { + if (auto name = os["name"].toString(); !name.isNull()) { + result.os = OS{ + name, + os["version"].toString(), + }; } } - ruleObj.insert("os", osObj); - return ruleObj; + + return result; +} + +QJsonObject Rule::toJson() +{ + QJsonObject result; + + if (action == Allow) + result["action"] = "allow"; + else if (action == Disallow) + result["action"] = "disallow"; + + if (os.has_value()) { + QJsonObject osResult; + + osResult["name"] = os->name; + + if (!os->version.isEmpty()) + osResult["version"] = os->version; + + result["os"] = osResult; + } + + return result; +} + +Rule::Action Rule::apply(const RuntimeContext& runtimeContext) +{ + if (!runtimeContext.classifierMatches(os->name)) + return Defer; + + return action; } diff --git a/launcher/minecraft/Rule.h b/launcher/minecraft/Rule.h index c6cdbc43f..c7d5f420e 100644 --- a/launcher/minecraft/Rule.h +++ b/launcher/minecraft/Rule.h @@ -2,6 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2025 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,59 +39,25 @@ #include #include #include -#include #include "RuntimeContext.h" class Library; -class Rule; -enum RuleAction { Allow, Disallow, Defer }; +struct Rule { + enum Action { Allow, Disallow, Defer }; -QList> rulesFromJsonV4(const QJsonObject& objectWithRules); + struct OS { + QString name; + // FIXME: unsupported + // retained to avoid information being lost from files + QString version; + }; -class Rule { - protected: - RuleAction m_result; - virtual bool applies(const Library* parent, const RuntimeContext& runtimeContext) = 0; + Action action = Defer; + std::optional os; - public: - Rule(RuleAction result) : m_result(result) {} - virtual ~Rule() {} - virtual QJsonObject toJson() = 0; - RuleAction apply(const Library* parent, const RuntimeContext& runtimeContext) - { - if (applies(parent, runtimeContext)) - return m_result; - else - return Defer; - } -}; - -class OsRule : public Rule { - private: - // the OS - QString m_system; - // the OS version regexp - QString m_version_regexp; - - protected: - virtual bool applies(const Library*, const RuntimeContext& runtimeContext) { return runtimeContext.classifierMatches(m_system); } - OsRule(RuleAction result, QString system, QString version_regexp) : Rule(result), m_system(system), m_version_regexp(version_regexp) {} - - public: - virtual QJsonObject toJson(); - static std::shared_ptr create(RuleAction result, QString system, QString version_regexp) - { - return std::shared_ptr(new OsRule(result, system, version_regexp)); - } -}; - -class ImplicitRule : public Rule { - protected: - virtual bool applies(const Library*, [[maybe_unused]] const RuntimeContext& runtimeContext) { return true; } - ImplicitRule(RuleAction result) : Rule(result) {} - - public: - virtual QJsonObject toJson(); - static std::shared_ptr create(RuleAction result) { return std::shared_ptr(new ImplicitRule(result)); } + static Rule fromJson(const QJsonObject& json); + QJsonObject toJson(); + + Action apply(const RuntimeContext& runtimeContext); }; From aaa1a748752fb9a0bc160822421348bb5118a1d9 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 4 Aug 2025 15:41:36 +0100 Subject: [PATCH 085/118] Reintroduce some encapulation As much as I like keeping things as simple as possible it's probably best to be consistent with other library related stuff Signed-off-by: TheKodeToad --- launcher/minecraft/Rule.cpp | 26 +++++++++++++------------- launcher/minecraft/Rule.h | 18 ++++++++++-------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/launcher/minecraft/Rule.cpp b/launcher/minecraft/Rule.cpp index 3cc655835..1a7c7c768 100644 --- a/launcher/minecraft/Rule.cpp +++ b/launcher/minecraft/Rule.cpp @@ -44,13 +44,13 @@ Rule Rule::fromJson(const QJsonObject& object) Rule result; if (object["action"] == "allow") - result.action = Allow; + result.m_action = Allow; else if (object["action"] == "disallow") - result.action = Disallow; + result.m_action = Disallow; if (auto os = object["os"]; os.isObject()) { if (auto name = os["name"].toString(); !name.isNull()) { - result.os = OS{ + result.m_os = OS{ name, os["version"].toString(), }; @@ -64,20 +64,20 @@ QJsonObject Rule::toJson() { QJsonObject result; - if (action == Allow) + if (m_action == Allow) result["action"] = "allow"; - else if (action == Disallow) + else if (m_action == Disallow) result["action"] = "disallow"; - if (os.has_value()) { - QJsonObject osResult; + if (m_os.has_value()) { + QJsonObject os; - osResult["name"] = os->name; + os["name"] = m_os->name; - if (!os->version.isEmpty()) - osResult["version"] = os->version; + if (!m_os->version.isEmpty()) + os["version"] = m_os->version; - result["os"] = osResult; + result["os"] = os; } return result; @@ -85,8 +85,8 @@ QJsonObject Rule::toJson() Rule::Action Rule::apply(const RuntimeContext& runtimeContext) { - if (!runtimeContext.classifierMatches(os->name)) + if (!runtimeContext.classifierMatches(m_os->name)) return Defer; - return action; + return m_action; } diff --git a/launcher/minecraft/Rule.h b/launcher/minecraft/Rule.h index c7d5f420e..b0b689fd7 100644 --- a/launcher/minecraft/Rule.h +++ b/launcher/minecraft/Rule.h @@ -43,9 +43,16 @@ class Library; -struct Rule { +class Rule { + public: enum Action { Allow, Disallow, Defer }; + static Rule fromJson(const QJsonObject& json); + QJsonObject toJson(); + + Action apply(const RuntimeContext& runtimeContext); + + private: struct OS { QString name; // FIXME: unsupported @@ -53,11 +60,6 @@ struct Rule { QString version; }; - Action action = Defer; - std::optional os; - - static Rule fromJson(const QJsonObject& json); - QJsonObject toJson(); - - Action apply(const RuntimeContext& runtimeContext); + Action m_action = Defer; + std::optional m_os; }; From 100b209043b9cf288d5e5a4566ee3fd408d2c3ff Mon Sep 17 00:00:00 2001 From: moehreag Date: Tue, 5 Aug 2025 10:27:49 +0200 Subject: [PATCH 086/118] Add Ornithe, LegacyFabric and Rift mod loader filters Signed-off-by: moehreag --- launcher/modplatform/ModIndex.cpp | 14 +++++++++++-- launcher/modplatform/ModIndex.h | 5 ++++- launcher/modplatform/flame/FlameAPI.h | 3 +++ .../import_ftb/PackInstallTask.cpp | 6 ++++++ launcher/modplatform/modrinth/ModrinthAPI.h | 4 ++-- launcher/ui/widgets/ModFilterWidget.cpp | 13 ++++++++++-- launcher/ui/widgets/ModFilterWidget.ui | 21 +++++++++++++++++++ 7 files changed, 59 insertions(+), 7 deletions(-) diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index edb5e5aa1..be2e5393e 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -31,7 +31,7 @@ static const QMap s_indexed_version_ty { "alpha", IndexedVersionType::VersionType::Alpha } }; -static const QList loaderList = { NeoForge, Forge, Cauldron, LiteLoader, Quilt, Fabric, Babric, BTA }; +static const QList loaderList = { NeoForge, Forge, Cauldron, LiteLoader, Quilt, Fabric, Babric, BTA, LegacyFabric, Ornithe }; QList modLoaderTypesToList(ModLoaderTypes flags) { @@ -122,7 +122,7 @@ auto getModLoaderAsString(ModLoaderType type) -> const QString case Cauldron: return "cauldron"; case LiteLoader: - return "liteloader"; + return "liteloader"; case Fabric: return "fabric"; case Quilt: @@ -133,6 +133,12 @@ auto getModLoaderAsString(ModLoaderType type) -> const QString return "babric"; case BTA: return "bta-babric"; + case LegacyFabric: + return "legacy-fabric"; + case Ornithe: + return "ornithe"; + case Rift: + return "rift"; default: break; } @@ -157,6 +163,10 @@ auto getModLoaderFromString(QString type) -> ModLoaderType return Babric; if (type == "bta-babric") return BTA; + if (type == "legacy-fabric") + return LegacyFabric; + if (type == "ornithe") + return Ornithe; return {}; } diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 2935eda76..07a256899 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -38,7 +38,10 @@ enum ModLoaderType { Quilt = 1 << 5, DataPack = 1 << 6, Babric = 1 << 7, - BTA = 1 << 8 + BTA = 1 << 8, + LegacyFabric = 1 << 9, + Ornithe = 1 << 10, + Rift = 1 << 11 }; Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType) QList modLoaderTypesToList(ModLoaderTypes flags); diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index f72bdb624..4b2b30645 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -73,6 +73,9 @@ class FlameAPI : public NetworkResourceAPI { case ModPlatform::DataPack: case ModPlatform::Babric: case ModPlatform::BTA: + case ModPlatform::LegacyFabric: + case ModPlatform::Ornithe: + case ModPlatform::Rift: break; // not supported } return 0; diff --git a/launcher/modplatform/import_ftb/PackInstallTask.cpp b/launcher/modplatform/import_ftb/PackInstallTask.cpp index 9ddca008d..3851e198c 100644 --- a/launcher/modplatform/import_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/import_ftb/PackInstallTask.cpp @@ -95,6 +95,12 @@ void PackInstallTask::copySettings() break; case ModPlatform::BTA: break; + case ModPlatform::LegacyFabric: + break; + case ModPlatform::Ornithe: + break; + case ModPlatform::Rift: + break; } components->saveNow(); diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 2e127dcff..5b426a06a 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -43,7 +43,7 @@ class ModrinthAPI : public NetworkResourceAPI { { QStringList l; for (auto loader : { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Fabric, ModPlatform::Quilt, ModPlatform::LiteLoader, - ModPlatform::DataPack, ModPlatform::Babric, ModPlatform::BTA }) { + ModPlatform::DataPack, ModPlatform::Babric, ModPlatform::BTA, ModPlatform::LegacyFabric, ModPlatform::Ornithe, ModPlatform::Rift }) { if (types & loader) { l << getModLoaderAsString(loader); } @@ -202,7 +202,7 @@ class ModrinthAPI : public NetworkResourceAPI { static inline auto validateModLoaders(ModPlatform::ModLoaderTypes loaders) -> bool { return loaders & (ModPlatform::NeoForge | ModPlatform::Forge | ModPlatform::Fabric | ModPlatform::Quilt | ModPlatform::LiteLoader | - ModPlatform::DataPack | ModPlatform::Babric | ModPlatform::BTA); + ModPlatform::DataPack | ModPlatform::Babric | ModPlatform::BTA | ModPlatform::LegacyFabric | ModPlatform::Ornithe | ModPlatform::Rift); } std::optional getDependencyURL(DependencySearchArgs const& args) const override diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index 654eb75b1..a19adabff 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -152,9 +152,12 @@ ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, bool extended) connect(ui->liteLoader, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); connect(ui->babric, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); connect(ui->btaBabric, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); - + connect(ui->legacyFabric, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); + connect(ui->ornithe, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); + connect(ui->rift, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); + connect(ui->showMoreButton, &QPushButton::clicked, this, &ModFilterWidget::onShowMoreClicked); - + if (!extended) { ui->showMoreButton->setVisible(false); ui->extendedModLoadersWidget->setVisible(false); @@ -289,6 +292,12 @@ void ModFilterWidget::onLoadersFilterChanged() loaders |= ModPlatform::Babric; if (ui->btaBabric->isChecked()) loaders |= ModPlatform::BTA; + if (ui->legacyFabric->isChecked()) + loaders |= ModPlatform::LegacyFabric; + if (ui->ornithe->isChecked()) + loaders |= ModPlatform::Ornithe; + if (ui->rift->isChecked()) + loaders |= ModPlatform::Rift; m_filter_changed = loaders != m_filter->loaders; m_filter->loaders = loaders; if (m_filter_changed) diff --git a/launcher/ui/widgets/ModFilterWidget.ui b/launcher/ui/widgets/ModFilterWidget.ui index 87d9af2e3..d29c9752a 100644 --- a/launcher/ui/widgets/ModFilterWidget.ui +++ b/launcher/ui/widgets/ModFilterWidget.ui @@ -167,6 +167,27 @@ + + + + Legacy Fabric + + + + + + + Ornithe + + + + + + + Rift + + + From 98ae99c513c59dfe6a1d49cb249f681d1f572424 Mon Sep 17 00:00:00 2001 From: moehreag Date: Tue, 5 Aug 2025 12:08:41 +0200 Subject: [PATCH 087/118] add Rift in the two places I missed Signed-off-by: moehreag --- launcher/modplatform/ModIndex.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index be2e5393e..b13087158 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -31,7 +31,7 @@ static const QMap s_indexed_version_ty { "alpha", IndexedVersionType::VersionType::Alpha } }; -static const QList loaderList = { NeoForge, Forge, Cauldron, LiteLoader, Quilt, Fabric, Babric, BTA, LegacyFabric, Ornithe }; +static const QList loaderList = { NeoForge, Forge, Cauldron, LiteLoader, Quilt, Fabric, Babric, BTA, LegacyFabric, Ornithe, Rift }; QList modLoaderTypesToList(ModLoaderTypes flags) { @@ -167,6 +167,8 @@ auto getModLoaderFromString(QString type) -> ModLoaderType return LegacyFabric; if (type == "ornithe") return Ornithe; + if (type == "rift") + return Rift; return {}; } From d1f7bcd6c690b7c0c28b92763d5fd5a513660a18 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 5 Aug 2025 18:55:07 +0100 Subject: [PATCH 088/118] Properly refresh modpack search upon changing filters Signed-off-by: TheKodeToad --- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 4 ++-- launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 9578eb73e..5bc314cc2 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -140,8 +140,8 @@ void FlamePage::triggerSearch() ui->packView->clearSelection(); ui->packDescription->clear(); ui->versionSelectionBox->clear(); - listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), m_filterWidget->getFilter(), - m_filterWidget->changed()); + bool filterChanged = m_filterWidget->changed(); + listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), m_filterWidget->getFilter(), filterChanged); m_fetch_progress.watch(listModel->activeSearchJob().get()); } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 4586bf70d..d9004a1fc 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -361,7 +361,8 @@ void ModrinthPage::triggerSearch() ui->packView->clearSelection(); ui->packDescription->clear(); ui->versionSelectionBox->clear(); - m_model->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), m_filterWidget->getFilter(), m_filterWidget->changed()); + bool filterChanged = m_filterWidget->changed(); + m_model->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), m_filterWidget->getFilter(), filterChanged); m_fetch_progress.watch(m_model->activeSearchJob().get()); } From 9f5bc882b211dd700fff5f879ac60d1e91e332a0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 02:15:15 +0000 Subject: [PATCH 089/118] chore(deps): update actions/download-artifact action to v5 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 264dffbc0..606c4f15a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: submodules: "true" path: "PrismLauncher-source" - name: Download artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 - name: Grab and store version run: | tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$") From 1cc6072a94a5cefb373f7d584d6e9d180dc7e893 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 10 Aug 2025 00:32:11 +0000 Subject: [PATCH 090/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/6e987485eb2c77e5dcc5af4e3c70843711ef9251?narHash=sha256-RKwfXA4OZROjBTQAl9WOZQFm7L8Bo93FQwSJpAiSRvo%3D' (2025-07-16) → 'github:NixOS/nixpkgs/c2ae88e026f9525daf89587f3cbee584b92b6134?narHash=sha256-erbiH2agUTD0Z30xcVSFcDHzkRvkRXOQ3lb887bcVrs%3D' (2025-08-06) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 162ad5baa..80131607b 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1752687322, - "narHash": "sha256-RKwfXA4OZROjBTQAl9WOZQFm7L8Bo93FQwSJpAiSRvo=", + "lastModified": 1754498491, + "narHash": "sha256-erbiH2agUTD0Z30xcVSFcDHzkRvkRXOQ3lb887bcVrs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6e987485eb2c77e5dcc5af4e3c70843711ef9251", + "rev": "c2ae88e026f9525daf89587f3cbee584b92b6134", "type": "github" }, "original": { From a1956ec53ad6d5157ad3e4a0590813bc73cfabd3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 06:44:42 +0000 Subject: [PATCH 091/118] chore(deps): update actions/cache action to v4.2.4 --- .github/actions/setup-dependencies/windows/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-dependencies/windows/action.yml b/.github/actions/setup-dependencies/windows/action.yml index 9b045610e..a91540c58 100644 --- a/.github/actions/setup-dependencies/windows/action.yml +++ b/.github/actions/setup-dependencies/windows/action.yml @@ -90,7 +90,7 @@ runs: - name: Retrieve ccache cache (MinGW) if: ${{ inputs.msystem != '' && inputs.build-type == 'Debug' }} - uses: actions/cache@v4.2.3 + uses: actions/cache@v4.2.4 with: path: '${{ github.workspace }}\.ccache' key: ${{ runner.os }}-mingw-w64-ccache-${{ github.run_id }} From 29dc75ec63a07ee55f51b2c0e27e1b6fb8227bc5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:25:38 +0000 Subject: [PATCH 092/118] chore(deps): update actions/checkout action to v5 --- .github/workflows/backport.yml | 2 +- .github/workflows/build.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/flatpak.yml | 2 +- .github/workflows/nix.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/update-flake.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index d8f9688d7..42369c366 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -21,7 +21,7 @@ jobs: if: github.repository_owner == 'PrismLauncher' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name)) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8ba57a45..dc72e2da0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -133,7 +133,7 @@ jobs: ## - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: true diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 964e322b1..924b81e5f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -60,7 +60,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: "true" diff --git a/.github/workflows/flatpak.yml b/.github/workflows/flatpak.yml index 1d5c5e9cc..c16917869 100644 --- a/.github/workflows/flatpak.yml +++ b/.github/workflows/flatpak.yml @@ -84,7 +84,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: true diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 6c7b2dac2..ca3803139 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -105,7 +105,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ steps.merge-commit.outputs.merge-commit-sha || github.sha }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 606c4f15a..5fed75215 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: "true" path: "PrismLauncher-source" diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 5822c411b..5648d5477 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: cachix/install-nix-action@c134e4c9e34bac6cab09cf239815f9339aaaf84e # v31 - uses: DeterminateSystems/update-flake-lock@v27 From a261718009e1f565464fdc02c75a5dc0e2f4b412 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 17:10:11 +0000 Subject: [PATCH 093/118] chore(deps): update korthout/backport-action action to v3.3.0 --- .github/workflows/backport.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index d8f9688d7..487bbd826 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -25,7 +25,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs - uses: korthout/backport-action@v3.2.1 + uses: korthout/backport-action@v3.3.0 with: # Config README: https://github.com/korthout/backport-action#backport-action pull_description: |- From bc76960dd7f2e284b2c821e740a8ae0c80a2efdd Mon Sep 17 00:00:00 2001 From: Seth Flynn Date: Fri, 15 Aug 2025 13:56:28 +0000 Subject: [PATCH 094/118] style(nix): format with modern nixfmt Signed-off-by: Seth Flynn --- nix/unwrapped.nix | 50 +++++++++++++++++------------------ nix/wrapper.nix | 67 +++++++++++++++++++++++------------------------ 2 files changed, 57 insertions(+), 60 deletions(-) diff --git a/nix/unwrapped.nix b/nix/unwrapped.nix index d9144410f..93ac21de0 100644 --- a/nix/unwrapped.nix +++ b/nix/unwrapped.nix @@ -76,35 +76,33 @@ stdenv.mkDerivation { stripJavaArchivesHook ]; - buildInputs = - [ - cmark - kdePackages.qtbase - kdePackages.qtnetworkauth - kdePackages.quazip - tomlplusplus - zlib - ] - ++ lib.optionals stdenv.hostPlatform.isDarwin [ apple-sdk_11 ] - ++ lib.optional gamemodeSupport gamemode; + buildInputs = [ + cmark + kdePackages.qtbase + kdePackages.qtnetworkauth + kdePackages.quazip + tomlplusplus + zlib + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ apple-sdk_11 ] + ++ lib.optional gamemodeSupport gamemode; hardeningEnable = lib.optionals stdenv.hostPlatform.isLinux [ "pie" ]; - cmakeFlags = - [ - # downstream branding - (lib.cmakeFeature "Launcher_BUILD_PLATFORM" "nixpkgs") - ] - ++ lib.optionals (msaClientID != null) [ - (lib.cmakeFeature "Launcher_MSA_CLIENT_ID" (toString msaClientID)) - ] - ++ lib.optionals stdenv.hostPlatform.isDarwin [ - # we wrap our binary manually - (lib.cmakeFeature "INSTALL_BUNDLE" "nodeps") - # disable built-in updater - (lib.cmakeFeature "MACOSX_SPARKLE_UPDATE_FEED_URL" "''") - (lib.cmakeFeature "CMAKE_INSTALL_PREFIX" "${placeholder "out"}/Applications/") - ]; + cmakeFlags = [ + # downstream branding + (lib.cmakeFeature "Launcher_BUILD_PLATFORM" "nixpkgs") + ] + ++ lib.optionals (msaClientID != null) [ + (lib.cmakeFeature "Launcher_MSA_CLIENT_ID" (toString msaClientID)) + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + # we wrap our binary manually + (lib.cmakeFeature "INSTALL_BUNDLE" "nodeps") + # disable built-in updater + (lib.cmakeFeature "MACOSX_SPARKLE_UPDATE_FEED_URL" "''") + (lib.cmakeFeature "CMAKE_INSTALL_PREFIX" "${placeholder "out"}/Applications/") + ]; doCheck = true; diff --git a/nix/wrapper.nix b/nix/wrapper.nix index 03c1f0421..01edd0d9a 100644 --- a/nix/wrapper.nix +++ b/nix/wrapper.nix @@ -61,14 +61,13 @@ symlinkJoin { nativeBuildInputs = [ kdePackages.wrapQtAppsHook ]; - buildInputs = - [ - kdePackages.qtbase - kdePackages.qtsvg - ] - ++ lib.optional ( - lib.versionAtLeast kdePackages.qtbase.version "6" && stdenv.hostPlatform.isLinux - ) kdePackages.qtwayland; + buildInputs = [ + kdePackages.qtbase + kdePackages.qtsvg + ] + ++ lib.optional ( + lib.versionAtLeast kdePackages.qtbase.version "6" && stdenv.hostPlatform.isLinux + ) kdePackages.qtwayland; postBuild = '' wrapQtAppsHook @@ -76,41 +75,41 @@ symlinkJoin { qtWrapperArgs = let - runtimeLibs = - [ - (lib.getLib stdenv.cc.cc) - ## native versions - glfw3-minecraft - openal + runtimeLibs = [ + (lib.getLib stdenv.cc.cc) + ## native versions + glfw3-minecraft + openal - ## openal - alsa-lib - libjack2 - libpulseaudio - pipewire + ## openal + alsa-lib + libjack2 + libpulseaudio + pipewire - ## glfw - libGL - libX11 - libXcursor - libXext - libXrandr - libXxf86vm + ## glfw + libGL + libX11 + libXcursor + libXext + libXrandr + libXxf86vm - udev # oshi + udev # oshi - vulkan-loader # VulkanMod's lwjgl - ] - ++ lib.optional textToSpeechSupport flite - ++ lib.optional gamemodeSupport gamemode.lib - ++ lib.optional controllerSupport libusb1 - ++ additionalLibs; + vulkan-loader # VulkanMod's lwjgl + ] + ++ lib.optional textToSpeechSupport flite + ++ lib.optional gamemodeSupport gamemode.lib + ++ lib.optional controllerSupport libusb1 + ++ additionalLibs; runtimePrograms = [ mesa-demos pciutils # need lspci xrandr # needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128 - ] ++ additionalPrograms; + ] + ++ additionalPrograms; in [ "--prefix PRISMLAUNCHER_JAVA_PATHS : ${lib.makeSearchPath "bin/java" jdks}" ] From 4d4b8a1fd0900eb0b28448ca96df1b8567210bca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 17 Aug 2025 00:30:33 +0000 Subject: [PATCH 095/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/c2ae88e026f9525daf89587f3cbee584b92b6134?narHash=sha256-erbiH2agUTD0Z30xcVSFcDHzkRvkRXOQ3lb887bcVrs%3D' (2025-08-06) → 'github:NixOS/nixpkgs/fbcf476f790d8a217c3eab4e12033dc4a0f6d23c?narHash=sha256-wNO3%2BKs2jZJ4nTHMuks%2BcxAiVBGNuEBXsT29Bz6HASo%3D' (2025-08-14) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 80131607b..15aef086a 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1754498491, - "narHash": "sha256-erbiH2agUTD0Z30xcVSFcDHzkRvkRXOQ3lb887bcVrs=", + "lastModified": 1755186698, + "narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c2ae88e026f9525daf89587f3cbee584b92b6134", + "rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c", "type": "github" }, "original": { From c596c6eb48015b8943d5148b094366f652a68cce Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 06:51:14 +0000 Subject: [PATCH 096/118] chore(deps): update actions/setup-java action to v5 --- .github/actions/setup-dependencies/windows/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-dependencies/windows/action.yml b/.github/actions/setup-dependencies/windows/action.yml index a91540c58..73840771c 100644 --- a/.github/actions/setup-dependencies/windows/action.yml +++ b/.github/actions/setup-dependencies/windows/action.yml @@ -26,7 +26,7 @@ runs: vsversion: 2022 - name: Setup Java (MSVC) - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: # NOTE(@getchoo): We should probably stay on Zulu. # Temurin doesn't have Java 17 builds for WoA From 31e0c07bf7bfb36207c5ad6d1cb7c56fd192dc59 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 21 Aug 2025 12:45:48 +0100 Subject: [PATCH 097/118] Fix #4083 - server address text box is enabled even if auto-join is disabled Signed-off-by: TheKodeToad --- launcher/ui/widgets/MinecraftSettingsWidget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/ui/widgets/MinecraftSettingsWidget.cpp b/launcher/ui/widgets/MinecraftSettingsWidget.cpp index f46786518..7cd84c8bb 100644 --- a/launcher/ui/widgets/MinecraftSettingsWidget.cpp +++ b/launcher/ui/widgets/MinecraftSettingsWidget.cpp @@ -222,9 +222,9 @@ void MinecraftSettingsWidget::loadSettings() m_ui->useDiscreteGpuCheck->setChecked(settings->get("UseDiscreteGpu").toBool()); m_ui->useZink->setChecked(settings->get("UseZink").toBool()); - m_ui->serverJoinGroupBox->setChecked(settings->get("JoinServerOnLaunch").toBool()); - if (m_instance != nullptr) { + m_ui->serverJoinGroupBox->setChecked(settings->get("JoinServerOnLaunch").toBool()); + if (auto server = settings->get("JoinServerOnLaunchAddress").toString(); !server.isEmpty()) { m_ui->serverJoinAddress->setText(server); m_ui->serverJoinAddressButton->setChecked(true); @@ -240,7 +240,7 @@ void MinecraftSettingsWidget::loadSettings() } else { m_ui->serverJoinAddressButton->setChecked(true); m_ui->worldJoinButton->setChecked(false); - m_ui->serverJoinAddress->setEnabled(true); + m_ui->serverJoinAddress->setEnabled(m_ui->serverJoinGroupBox->isChecked()); m_ui->worldsCb->setEnabled(false); } From 8c9b504382b665116e836b35774b4d73fc6f544a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 21 Aug 2025 14:48:22 +0300 Subject: [PATCH 098/118] fix: datapack/resourcepack parsing Signed-off-by: Trial97 --- launcher/minecraft/mod/DataPack.h | 2 -- launcher/minecraft/mod/ResourcePack.h | 2 -- .../minecraft/mod/tasks/LocalDataPackParseTask.cpp | 10 ---------- 3 files changed, 14 deletions(-) diff --git a/launcher/minecraft/mod/DataPack.h b/launcher/minecraft/mod/DataPack.h index ac6408bde..2943dd4bc 100644 --- a/launcher/minecraft/mod/DataPack.h +++ b/launcher/minecraft/mod/DataPack.h @@ -64,8 +64,6 @@ class DataPack : public Resource { [[nodiscard]] int compare(Resource const& other, SortType type) const override; [[nodiscard]] bool applyFilter(QRegularExpression filter) const override; - virtual QString directory() { return "/data"; } - protected: mutable QMutex m_data_lock; diff --git a/launcher/minecraft/mod/ResourcePack.h b/launcher/minecraft/mod/ResourcePack.h index 494bdee97..9345e9c27 100644 --- a/launcher/minecraft/mod/ResourcePack.h +++ b/launcher/minecraft/mod/ResourcePack.h @@ -23,6 +23,4 @@ class ResourcePack : public DataPack { /** Gets, respectively, the lower and upper versions supported by the set pack format. */ std::pair compatibleVersions() const override; - - QString directory() override { return "/assets"; } }; diff --git a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp index c37a25c21..c63e0c65f 100644 --- a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp @@ -73,11 +73,6 @@ bool processFolder(DataPack* pack, ProcessingLevel level) return mcmeta_invalid(); // mcmeta file isn't a valid file } - QFileInfo data_dir_info(FS::PathCombine(pack->fileinfo().filePath(), pack->directory())); - if (!data_dir_info.exists() || !data_dir_info.isDir()) { - return false; // data dir does not exists or isn't valid - } - if (level == ProcessingLevel::BasicInfoOnly) { return true; // only need basic info already checked } @@ -141,11 +136,6 @@ bool processZIP(DataPack* pack, ProcessingLevel level) return mcmeta_invalid(); // could not set pack.mcmeta as current file. } - QuaZipDir zipDir(&zip); - if (!zipDir.exists(pack->directory())) { - return false; // data dir does not exists at zip root - } - if (level == ProcessingLevel::BasicInfoOnly) { zip.close(); return true; // only need basic info already checked From 22d651f0417a304ac0b22b86ad767d6066deb5bd Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 21 Aug 2025 13:05:13 +0100 Subject: [PATCH 099/118] Fix buggy movement in screenshots page Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/ScreenshotsPage.ui | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/instance/ScreenshotsPage.ui b/launcher/ui/pages/instance/ScreenshotsPage.ui index 2e2227a29..db55869cd 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.ui +++ b/launcher/ui/pages/instance/ScreenshotsPage.ui @@ -26,11 +26,17 @@ + + false + - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - QAbstractItemView::SelectRows + QAbstractItemView::SelectionBehavior::SelectRows + + + QListView::Movement::Static @@ -41,7 +47,7 @@ Actions - Qt::ToolButtonTextOnly + Qt::ToolButtonStyle::ToolButtonTextOnly RightToolBarArea From 634a5d18c490e9ab8a7106456daddebd1ee916af Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 21 Aug 2025 15:14:05 +0300 Subject: [PATCH 100/118] fix tests Signed-off-by: Trial97 --- tests/ResourcePackParse_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ResourcePackParse_test.cpp b/tests/ResourcePackParse_test.cpp index e9b5244ad..5400d888a 100644 --- a/tests/ResourcePackParse_test.cpp +++ b/tests/ResourcePackParse_test.cpp @@ -69,7 +69,7 @@ class ResourcePackParseTest : public QObject { QVERIFY(pack.packFormat() == 6); QVERIFY(pack.description() == "o quartel pegou fogo, policia deu sinal, acode acode acode a bandeira nacional"); - QVERIFY(valid == false); // no assets dir + QVERIFY(valid == true); // no assets dir but it is still valid based on https://minecraft.wiki/w/Resource_pack } }; From 40f45b19f403ab2683b8e4288fdcb2d518371bcf Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 21 Aug 2025 13:31:03 +0100 Subject: [PATCH 101/118] Make search bars consistent Signed-off-by: TheKodeToad --- .../pages/instance/ExternalResourcesPage.ui | 44 ++++++++----------- launcher/ui/pages/instance/LogPage.ui | 30 ++++++++----- launcher/ui/pages/instance/OtherLogsPage.ui | 29 +++++++----- launcher/ui/pages/instance/VersionPage.ui | 17 +++---- 4 files changed, 61 insertions(+), 59 deletions(-) diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 5df8aafa2..f55218ae5 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -24,31 +24,7 @@ 0 - - - - - - - - - Filter: - - - - - - - - - - 0 - 0 - - - - - + @@ -67,6 +43,23 @@ + + + + + 0 + 0 + + + + + + + + Search + + + @@ -247,7 +240,6 @@ treeView - filterEdit diff --git a/launcher/ui/pages/instance/LogPage.ui b/launcher/ui/pages/instance/LogPage.ui index fb8690581..66a432edb 100644 --- a/launcher/ui/pages/instance/LogPage.ui +++ b/launcher/ui/pages/instance/LogPage.ui @@ -129,25 +129,27 @@ - - - - Search: - - - + + + 0 + 0 + + Find - - - + + + 0 + 0 + + Scroll all the way to bottom @@ -163,6 +165,13 @@ + + + + Search + + + @@ -185,7 +194,6 @@ btnPaste btnClear text - searchBar findButton diff --git a/launcher/ui/pages/instance/OtherLogsPage.ui b/launcher/ui/pages/instance/OtherLogsPage.ui index 7d60de5c4..be08e0fdb 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.ui +++ b/launcher/ui/pages/instance/OtherLogsPage.ui @@ -33,18 +33,14 @@ Tab 1 - - - - Search: - - - - - - + + + 0 + 0 + + &Find @@ -59,6 +55,12 @@ + + + 0 + 0 + + Scroll all the way to bottom @@ -204,6 +206,13 @@ + + + + Search + + + diff --git a/launcher/ui/pages/instance/VersionPage.ui b/launcher/ui/pages/instance/VersionPage.ui index 9be21d499..d525f56a5 100644 --- a/launcher/ui/pages/instance/VersionPage.ui +++ b/launcher/ui/pages/instance/VersionPage.ui @@ -43,18 +43,11 @@ - - - - - - - - Filter: - - - - + + + Search + + From 81e4f1cf7aabc98499a779475f1eac2afd9f89bd Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 21 Aug 2025 13:49:49 +0100 Subject: [PATCH 102/118] Prevent View Configs showing in places it shouldn't Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/ExternalResourcesPage.cpp | 2 +- launcher/ui/pages/instance/ExternalResourcesPage.ui | 11 +++++------ launcher/ui/pages/instance/ModFolderPage.cpp | 2 ++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index d38d16284..d0fb2347b 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -52,7 +52,7 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared { ui->setupUi(this); - ui->actionsToolbar->insertSpacer(ui->actionViewConfigs); + ui->actionsToolbar->insertSpacer(ui->actionViewFolder); m_filterModel = model->createFilterProxyModel(this); m_filterModel->setDynamicSortFilter(true); diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index f55218ae5..c6955d0ce 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -36,7 +36,7 @@ true - QAbstractItemView::DropOnly + QAbstractItemView::DragDropMode::DropOnly true @@ -67,7 +67,7 @@ Actions - Qt::ToolButtonIconOnly + Qt::ToolButtonStyle::ToolButtonIconOnly true @@ -85,7 +85,6 @@ - @@ -172,7 +171,7 @@ Reset Update Metadata - QAction::NoRole + QAction::MenuRole::NoRole @@ -180,7 +179,7 @@ Verify Dependencies - QAction::NoRole + QAction::MenuRole::NoRole @@ -205,7 +204,7 @@ Change a resource's version. - QAction::NoRole + QAction::MenuRole::NoRole diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 7b79766ee..198f336f9 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -106,6 +106,8 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionExportMetadata->setToolTip(tr("Export mod's metadata to text.")); connect(ui->actionExportMetadata, &QAction::triggered, this, &ModFolderPage::exportModMetadata); ui->actionsToolbar->insertActionAfter(ui->actionViewHomepage, ui->actionExportMetadata); + + ui->actionsToolbar->insertActionAfter(ui->actionViewFolder, ui->actionViewConfigs); } bool ModFolderPage::shouldDisplay() const From 83736950d9e63879312b8f432fb823cbbe3476d9 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 21 Aug 2025 14:06:26 +0100 Subject: [PATCH 103/118] Consistent case style Signed-off-by: TheKodeToad --- launcher/InstancePageProvider.h | 2 +- launcher/ui/MainWindow.ui | 2 +- launcher/ui/pages/global/ProxyPage.ui | 2 +- launcher/ui/pages/instance/DataPackPage.h | 2 +- launcher/ui/pages/instance/ManagedPackPage.cpp | 2 +- launcher/ui/pages/instance/ManagedPackPage.ui | 6 +++--- launcher/ui/pages/instance/ModFolderPage.h | 2 +- launcher/ui/pages/instance/ResourcePackPage.h | 2 +- launcher/ui/pages/instance/ShaderPackPage.h | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h index 258ed5aa5..d7e985dd2 100644 --- a/launcher/InstancePageProvider.h +++ b/launcher/InstancePageProvider.h @@ -46,7 +46,7 @@ class InstancePageProvider : protected QObject, public BasePageProvider { // values.append(new GameOptionsPage(onesix.get())); values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); values.append(new InstanceSettingsPage(onesix)); - values.append(new OtherLogsPage("logs", tr("Other logs"), "Other-Logs", inst)); + values.append(new OtherLogsPage("logs", tr("Other Logs"), "Other-Logs", inst)); return values; } diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 1d29ff628..ff1b4a25a 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -239,7 +239,7 @@ - More news... + More News... Open the development blog to read more news about %1. diff --git a/launcher/ui/pages/global/ProxyPage.ui b/launcher/ui/pages/global/ProxyPage.ui index dec8d0a26..436a90ad1 100644 --- a/launcher/ui/pages/global/ProxyPage.ui +++ b/launcher/ui/pages/global/ProxyPage.ui @@ -51,7 +51,7 @@ Uses your system's default proxy settings. - Use S&ystem Settings + Use s&ystem settings proxyGroup diff --git a/launcher/ui/pages/instance/DataPackPage.h b/launcher/ui/pages/instance/DataPackPage.h index 6676c165a..b71ed2965 100644 --- a/launcher/ui/pages/instance/DataPackPage.h +++ b/launcher/ui/pages/instance/DataPackPage.h @@ -28,7 +28,7 @@ class DataPackPage : public ExternalResourcesPage { public: explicit DataPackPage(BaseInstance* instance, std::shared_ptr model, QWidget* parent = nullptr); - QString displayName() const override { return QObject::tr("Data packs"); } + QString displayName() const override { return QObject::tr("Data Packs"); } QIcon icon() const override { return APPLICATION->getThemedIcon("datapacks"); } QString id() const override { return "datapacks"; } QString helpPage() const override { return "Data-packs"; } diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index a95762b5d..01bc6c2fd 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -213,7 +213,7 @@ bool ManagedPackPage::runUpdateTask(InstanceTask* task) void ManagedPackPage::suggestVersion() { - ui->updateButton->setText(tr("Update pack")); + ui->updateButton->setText(tr("Update Pack")); ui->updateButton->setDisabled(false); } diff --git a/launcher/ui/pages/instance/ManagedPackPage.ui b/launcher/ui/pages/instance/ManagedPackPage.ui index 54ff08e94..14b29a249 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.ui +++ b/launcher/ui/pages/instance/ManagedPackPage.ui @@ -34,7 +34,7 @@ - Pack information + Pack Information @@ -42,7 +42,7 @@ - Pack name: + Pack Name: @@ -162,7 +162,7 @@ - Update from file + Update From File diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index 8996b1615..9b9665571 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -82,7 +82,7 @@ class CoreModFolderPage : public ModFolderPage { explicit CoreModFolderPage(BaseInstance* inst, std::shared_ptr mods, QWidget* parent = 0); virtual ~CoreModFolderPage() = default; - virtual QString displayName() const override { return tr("Core mods"); } + virtual QString displayName() const override { return tr("Core Mods"); } virtual QIcon icon() const override { return APPLICATION->getThemedIcon("coremods"); } virtual QString id() const override { return "coremods"; } virtual QString helpPage() const override { return "Core-mods"; } diff --git a/launcher/ui/pages/instance/ResourcePackPage.h b/launcher/ui/pages/instance/ResourcePackPage.h index e39d417c9..40fe10b79 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.h +++ b/launcher/ui/pages/instance/ResourcePackPage.h @@ -50,7 +50,7 @@ class ResourcePackPage : public ExternalResourcesPage { public: explicit ResourcePackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent = 0); - QString displayName() const override { return tr("Resource packs"); } + QString displayName() const override { return tr("Resource Packs"); } QIcon icon() const override { return APPLICATION->getThemedIcon("resourcepacks"); } QString id() const override { return "resourcepacks"; } QString helpPage() const override { return "Resource-packs"; } diff --git a/launcher/ui/pages/instance/ShaderPackPage.h b/launcher/ui/pages/instance/ShaderPackPage.h index f2b141329..128c48ae7 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.h +++ b/launcher/ui/pages/instance/ShaderPackPage.h @@ -47,7 +47,7 @@ class ShaderPackPage : public ExternalResourcesPage { explicit ShaderPackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent = nullptr); ~ShaderPackPage() override = default; - QString displayName() const override { return tr("Shader packs"); } + QString displayName() const override { return tr("Shader Packs"); } QIcon icon() const override { return APPLICATION->getThemedIcon("shaderpacks"); } QString id() const override { return "shaderpacks"; } QString helpPage() const override { return "shader-packs"; } From 2b0d135afd76b31062327620d2aba959ddd343ac Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 21 Aug 2025 15:01:30 +0100 Subject: [PATCH 104/118] More consistent padding and frames Signed-off-by: TheKodeToad --- launcher/ui/pages/global/JavaPage.ui | 4 +- launcher/ui/pages/instance/LogPage.cpp | 1 - launcher/ui/pages/instance/LogPage.ui | 292 +++++++-------- launcher/ui/pages/instance/ManagedPackPage.ui | 8 +- launcher/ui/pages/instance/OtherLogsPage.cpp | 1 - launcher/ui/pages/instance/OtherLogsPage.ui | 337 +++++++++--------- .../ui/widgets/MinecraftSettingsWidget.ui | 10 +- 7 files changed, 309 insertions(+), 344 deletions(-) diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index a40e38868..3ed28cf30 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -24,7 +24,7 @@ 0 - 0 + 6 0 @@ -50,7 +50,7 @@ 0 0 535 - 606 + 612 diff --git a/launcher/ui/pages/instance/LogPage.cpp b/launcher/ui/pages/instance/LogPage.cpp index 9a7ce6039..928368236 100644 --- a/launcher/ui/pages/instance/LogPage.cpp +++ b/launcher/ui/pages/instance/LogPage.cpp @@ -131,7 +131,6 @@ QModelIndex LogFormatProxyModel::find(const QModelIndex& start, const QString& v LogPage::LogPage(InstancePtr instance, QWidget* parent) : QWidget(parent), ui(new Ui::LogPage), m_instance(instance) { ui->setupUi(this); - ui->tabWidget->tabBar()->hide(); m_proxy = new LogFormatProxyModel(this); diff --git a/launcher/ui/pages/instance/LogPage.ui b/launcher/ui/pages/instance/LogPage.ui index 66a432edb..2362e19c0 100644 --- a/launcher/ui/pages/instance/LogPage.ui +++ b/launcher/ui/pages/instance/LogPage.ui @@ -10,170 +10,153 @@ 782 - + 0 0 - - 0 - 0 - - - - 0 + + + + false + + + true + + + + + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + false + + + + + + + + + Keep updating + + + true + + + + + + + Wrap lines + + + true + + + + + + + Color lines + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Copy the whole log into the clipboard + + + &Copy + + + + + + + Upload the log to the paste service configured in preferences + + + Upload + + + + + + + Clear the log + + + Clear + + + + + + + + + + 0 + 0 + + + + Find + + + + + + + + 0 + 0 + + + + Scroll all the way to bottom + + + Bottom + + + + + + + Qt::Vertical + + + + + + + Search - - - Tab 1 - - - - - - false - - - true - - - - - - Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - false - - - - - - - - - Keep updating - - - true - - - - - - - Wrap lines - - - true - - - - - - - Color lines - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Copy the whole log into the clipboard - - - &Copy - - - - - - - Upload the log to the paste service configured in preferences - - - Upload - - - - - - - Clear the log - - - Clear - - - - - - - - - - 0 - 0 - - - - Find - - - - - - - - 0 - 0 - - - - Scroll all the way to bottom - - - Bottom - - - - - - - Qt::Vertical - - - - - - - Search - - - - - @@ -186,7 +169,6 @@ - tabWidget trackLogCheckbox wrapCheckbox colorCheckbox diff --git a/launcher/ui/pages/instance/ManagedPackPage.ui b/launcher/ui/pages/instance/ManagedPackPage.ui index 14b29a249..62641bc82 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.ui +++ b/launcher/ui/pages/instance/ManagedPackPage.ui @@ -12,16 +12,16 @@ - 9 + 0 - 9 + 0 - 9 + 6 - 9 + 0 diff --git a/launcher/ui/pages/instance/OtherLogsPage.cpp b/launcher/ui/pages/instance/OtherLogsPage.cpp index 6f98db4a8..69e152475 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.cpp +++ b/launcher/ui/pages/instance/OtherLogsPage.cpp @@ -61,7 +61,6 @@ OtherLogsPage::OtherLogsPage(QString id, QString displayName, QString helpPage, , m_logSearchPaths(instance ? instance->getLogFileSearchPaths() : QStringList{ "logs" }) { ui->setupUi(this); - ui->tabWidget->tabBar()->hide(); m_proxy = new LogFormatProxyModel(this); if (m_instance) { diff --git a/launcher/ui/pages/instance/OtherLogsPage.ui b/launcher/ui/pages/instance/OtherLogsPage.ui index be08e0fdb..77076d4ab 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.ui +++ b/launcher/ui/pages/instance/OtherLogsPage.ui @@ -10,7 +10,7 @@ 538 - + 0 @@ -18,203 +18,189 @@ 0 - 0 + 6 0 - - - - 0 + + + + + 0 + 0 + - - - Tab 1 - - - - + + &Find + + + + + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + Scroll all the way to bottom + + + &Bottom + + + + + + + false + + + false + + + true + + + + + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + false + + + + + + + + + - + 0 0 - - &Find - - - - - Qt::Vertical - - - - - - - - 0 - 0 - - + + - Scroll all the way to bottom + Delete the selected log - &Bottom + &Delete Selected - - - - false + + + + Delete all the logs - - false - - - true - - - - - - Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - false - - - - - - - - - - - - 0 - 0 - - - - - - - - Delete the selected log - - - &Delete Selected - - - - - - - Delete all the logs - - - Delete &All - - - - - - - - - - - Keep updating - - - true - - - - - - - Wrap lines - - - true - - - - - - - Color lines - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Copy the whole log into the clipboard - - - &Copy - - - - - - - Upload the log to the paste service configured in preferences - - - &Upload - - - - - - - Reload the contents of the log from the disk - - - &Reload - - - - - - - - - - - Search + + Delete &All - + + + + + + + Keep updating + + + true + + + + + + + Wrap lines + + + true + + + + + + + Color lines + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Copy the whole log into the clipboard + + + &Copy + + + + + + + Upload the log to the paste service configured in preferences + + + &Upload + + + + + + + Reload the contents of the log from the disk + + + &Reload + + + + + + + + + + + Search + @@ -227,7 +213,6 @@ - tabWidget selectLogBox btnReload btnCopy diff --git a/launcher/ui/widgets/MinecraftSettingsWidget.ui b/launcher/ui/widgets/MinecraftSettingsWidget.ui index 4a35addc0..f8ee2f854 100644 --- a/launcher/ui/widgets/MinecraftSettingsWidget.ui +++ b/launcher/ui/widgets/MinecraftSettingsWidget.ui @@ -18,7 +18,7 @@ 0 - 0 + 6 0 @@ -553,8 +553,8 @@ It is most likely you will need to change the path - please refer to the mod's w 0 0 - 624 - 487 + 100 + 30 @@ -577,8 +577,8 @@ It is most likely you will need to change the path - please refer to the mod's w 0 0 - 624 - 487 + 261 + 434 From 9ecc11787f8004673b51214dbd3bff0e1ad74e71 Mon Sep 17 00:00:00 2001 From: Cinnamon Date: Sun, 31 Aug 2025 10:14:40 -0500 Subject: [PATCH 105/118] Update TranslationsModel.cpp Signed-off-by: Cinnamon --- launcher/translations/TranslationsModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 75fc93b3b..860e57e54 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -73,7 +73,7 @@ struct Language { if (key == "ja_KANJI") { result = locale.nativeLanguageName() + u8" (漢字)"; } else if (key == "es_UY") { - result = u8"español de Latinoamérica"; + result = u8"Español de Latinoamérica"; } else if (key == "en_NZ") { result = u8"New Zealand English"; // No idea why qt translates this to just english and not to New Zealand English } else if (key == "en@pirate") { From e5653b36ccf3af0e835f2573dccce41d8d2aee6f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 04:47:44 +0000 Subject: [PATCH 106/118] chore(deps): update actions/stale action to v10 --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 106a7844f..b8f8137d7 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,7 +17,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v9 + - uses: actions/stale@v10 with: days-before-stale: 60 days-before-close: -1 # Don't close anything From 7e0b9511b4e854b874824fbb172274e0ccf7e5a9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 6 Sep 2025 12:54:37 +0000 Subject: [PATCH 107/118] chore(deps): update cachix/install-nix-action digest to 56a7bb7 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 5648d5477..9f2139f7b 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v5 - - uses: cachix/install-nix-action@c134e4c9e34bac6cab09cf239815f9339aaaf84e # v31 + - uses: cachix/install-nix-action@56a7bb7b56d9a92d4fd1bc05758de7eea4a370a8 # v31 - uses: DeterminateSystems/update-flake-lock@v27 with: From d9e5afcaa0166c50a8412e2d125278565d69c4f0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 7 Sep 2025 00:27:45 +0000 Subject: [PATCH 108/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/fbcf476f790d8a217c3eab4e12033dc4a0f6d23c?narHash=sha256-wNO3%2BKs2jZJ4nTHMuks%2BcxAiVBGNuEBXsT29Bz6HASo%3D' (2025-08-14) → 'github:NixOS/nixpkgs/d0fc30899600b9b3466ddb260fd83deb486c32f1?narHash=sha256-rw/PHa1cqiePdBxhF66V7R%2BWAP8WekQ0mCDG4CFqT8Y%3D' (2025-09-02) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 15aef086a..f6a467306 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1755186698, - "narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=", + "lastModified": 1756787288, + "narHash": "sha256-rw/PHa1cqiePdBxhF66V7R+WAP8WekQ0mCDG4CFqT8Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c", + "rev": "d0fc30899600b9b3466ddb260fd83deb486c32f1", "type": "github" }, "original": { From 170071746f52fff6e8e18183c6fc587ea190e847 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Sep 2025 17:48:01 +0000 Subject: [PATCH 109/118] chore(deps): update hendrikmuhs/ccache-action action to v1.2.19 --- .github/actions/setup-dependencies/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-dependencies/action.yml b/.github/actions/setup-dependencies/action.yml index 6c718f9e3..82395eada 100644 --- a/.github/actions/setup-dependencies/action.yml +++ b/.github/actions/setup-dependencies/action.yml @@ -56,7 +56,7 @@ runs: # TODO(@getchoo): Get this working on MSYS2! - name: Setup ccache if: ${{ (runner.os != 'Windows' || inputs.msystem == '') && inputs.build-type == 'Debug' }} - uses: hendrikmuhs/ccache-action@v1.2.18 + uses: hendrikmuhs/ccache-action@v1.2.19 with: variant: sccache create-symlink: ${{ runner.os != 'Windows' }} From 7f4b157087ca07bc84cd50846ed0e35aa64952ba Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 13 Sep 2025 06:24:19 +0000 Subject: [PATCH 110/118] chore(deps): update cachix/install-nix-action digest to 7be5dee --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 9f2139f7b..f1821646a 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v5 - - uses: cachix/install-nix-action@56a7bb7b56d9a92d4fd1bc05758de7eea4a370a8 # v31 + - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31 - uses: DeterminateSystems/update-flake-lock@v27 with: From 89d7ffdc685aea54092bb6c10d3f32e2e93c3cac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 14 Sep 2025 00:27:15 +0000 Subject: [PATCH 111/118] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/d0fc30899600b9b3466ddb260fd83deb486c32f1?narHash=sha256-rw/PHa1cqiePdBxhF66V7R%2BWAP8WekQ0mCDG4CFqT8Y%3D' (2025-09-02) → 'github:NixOS/nixpkgs/c23193b943c6c689d70ee98ce3128239ed9e32d1?narHash=sha256-hLEO2TPj55KcUFUU1vgtHE9UEIOjRcH/4QbmfHNF820%3D' (2025-09-13) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index f6a467306..70625e923 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1756787288, - "narHash": "sha256-rw/PHa1cqiePdBxhF66V7R+WAP8WekQ0mCDG4CFqT8Y=", + "lastModified": 1757745802, + "narHash": "sha256-hLEO2TPj55KcUFUU1vgtHE9UEIOjRcH/4QbmfHNF820=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d0fc30899600b9b3466ddb260fd83deb486c32f1", + "rev": "c23193b943c6c689d70ee98ce3128239ed9e32d1", "type": "github" }, "original": { From ab3bfb0f74bacc8f9e27f574b928624633df4a51 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 24 Mar 2025 23:06:53 +0200 Subject: [PATCH 112/118] make universal resource type Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index c66fb5655..514b33574 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -38,6 +38,7 @@ #include "BuildConfig.h" #include "Json.h" +#include "modplatform/ModIndex.h" #include "modplatform/modrinth/ModrinthAPI.h" #include "net/NetJob.h" #include "ui/widgets/ProjectItem.h" From 29cff14fd6166e2b885955e72126274f3e48c76b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 30 Mar 2025 00:32:59 +0200 Subject: [PATCH 113/118] removed some duplicate code Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 9 +- .../mod/tasks/GetModDependenciesTask.cpp | 85 ++--- .../mod/tasks/GetModDependenciesTask.h | 22 +- launcher/modplatform/ModIndex.h | 17 + ...NetworkResourceAPI.cpp => ResourceAPI.cpp} | 260 +++++++++++----- launcher/modplatform/ResourceAPI.h | 115 +++---- launcher/modplatform/flame/FlameAPI.h | 25 +- launcher/modplatform/flame/FlameModIndex.cpp | 30 +- launcher/modplatform/flame/FlameModIndex.h | 3 +- launcher/modplatform/flame/FlamePackIndex.cpp | 150 --------- launcher/modplatform/flame/FlamePackIndex.h | 55 ---- .../modplatform/helpers/NetworkResourceAPI.h | 25 -- launcher/modplatform/modrinth/ModrinthAPI.h | 14 +- .../modrinth/ModrinthInstanceCreationTask.cpp | 9 +- .../modrinth/ModrinthInstanceCreationTask.h | 22 +- .../modrinth/ModrinthPackIndex.cpp | 44 --- .../modplatform/modrinth/ModrinthPackIndex.h | 2 - .../modrinth/ModrinthPackManifest.cpp | 196 ------------ .../modrinth/ModrinthPackManifest.h | 129 -------- .../ui/pages/instance/ManagedPackPage.cpp | 99 ++---- launcher/ui/pages/instance/ManagedPackPage.h | 11 +- .../ui/pages/modplatform/DataPackModel.cpp | 4 +- launcher/ui/pages/modplatform/DataPackModel.h | 11 +- launcher/ui/pages/modplatform/ModModel.cpp | 6 +- launcher/ui/pages/modplatform/ModModel.h | 15 +- .../ui/pages/modplatform/ResourceModel.cpp | 197 ++++-------- launcher/ui/pages/modplatform/ResourceModel.h | 32 +- .../pages/modplatform/ResourcePackModel.cpp | 9 +- .../ui/pages/modplatform/ResourcePackModel.h | 11 +- .../ui/pages/modplatform/ShaderPackModel.cpp | 6 +- .../ui/pages/modplatform/ShaderPackModel.h | 11 +- .../ui/pages/modplatform/TexturePackModel.cpp | 5 +- .../ui/pages/modplatform/TexturePackModel.h | 2 +- .../ui/pages/modplatform/flame/FlameModel.cpp | 159 ++++------ .../ui/pages/modplatform/flame/FlameModel.h | 25 +- .../ui/pages/modplatform/flame/FlamePage.cpp | 226 ++++++-------- .../ui/pages/modplatform/flame/FlamePage.h | 11 +- .../modplatform/flame/FlameResourceModels.cpp | 157 +--------- .../modplatform/flame/FlameResourceModels.h | 86 ----- .../modplatform/flame/FlameResourcePages.cpp | 12 +- .../modplatform/modrinth/ModrinthModel.cpp | 160 ++++------ .../modplatform/modrinth/ModrinthModel.h | 30 +- .../modplatform/modrinth/ModrinthPage.cpp | 294 ++++++++---------- .../pages/modplatform/modrinth/ModrinthPage.h | 21 +- .../modrinth/ModrinthResourceModels.cpp | 144 --------- .../modrinth/ModrinthResourceModels.h | 121 ------- .../modrinth/ModrinthResourcePages.cpp | 16 +- .../ui/widgets/MinecraftSettingsWidget.cpp | 1 + launcher/ui/widgets/ModFilterWidget.h | 8 + tests/CMakeLists.txt | 3 - tests/DummyResourceAPI.h | 46 --- tests/ResourceModel_test.cpp | 95 ------ 52 files changed, 928 insertions(+), 2318 deletions(-) rename launcher/modplatform/{helpers/NetworkResourceAPI.cpp => ResourceAPI.cpp} (51%) delete mode 100644 launcher/modplatform/flame/FlamePackIndex.cpp delete mode 100644 launcher/modplatform/flame/FlamePackIndex.h delete mode 100644 launcher/modplatform/helpers/NetworkResourceAPI.h delete mode 100644 launcher/modplatform/modrinth/ModrinthPackManifest.cpp delete mode 100644 launcher/modplatform/modrinth/ModrinthPackManifest.h delete mode 100644 launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp delete mode 100644 launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h delete mode 100644 tests/DummyResourceAPI.h delete mode 100644 tests/ResourceModel_test.cpp diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 2d1c62269..c0b4894d7 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -488,6 +488,7 @@ set(API_SOURCES modplatform/ResourceType.cpp modplatform/ResourceAPI.h + modplatform/ResourceAPI.cpp modplatform/EnsureMetadataTask.h modplatform/EnsureMetadataTask.cpp @@ -498,8 +499,6 @@ set(API_SOURCES modplatform/flame/FlameAPI.cpp modplatform/modrinth/ModrinthAPI.h modplatform/modrinth/ModrinthAPI.cpp - modplatform/helpers/NetworkResourceAPI.h - modplatform/helpers/NetworkResourceAPI.cpp modplatform/helpers/HashUtils.h modplatform/helpers/HashUtils.cpp modplatform/helpers/OverrideUtils.h @@ -527,8 +526,6 @@ set(FTB_SOURCES set(FLAME_SOURCES # Flame - modplatform/flame/FlamePackIndex.cpp - modplatform/flame/FlamePackIndex.h modplatform/flame/FlameModIndex.cpp modplatform/flame/FlameModIndex.h modplatform/flame/PackManifest.h @@ -546,8 +543,6 @@ set(FLAME_SOURCES set(MODRINTH_SOURCES modplatform/modrinth/ModrinthPackIndex.cpp modplatform/modrinth/ModrinthPackIndex.h - modplatform/modrinth/ModrinthPackManifest.cpp - modplatform/modrinth/ModrinthPackManifest.h modplatform/modrinth/ModrinthCheckUpdate.cpp modplatform/modrinth/ModrinthCheckUpdate.h modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -1035,8 +1030,6 @@ SET(LAUNCHER_SOURCES ui/pages/modplatform/OptionalModDialog.cpp ui/pages/modplatform/OptionalModDialog.h - ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp - ui/pages/modplatform/modrinth/ModrinthResourceModels.h ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp ui/pages/modplatform/modrinth/ModrinthResourcePages.h diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 21e7c5a2a..75815cb44 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -27,12 +27,8 @@ #include "minecraft/mod/MetadataHandler.h" #include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" -#include "modplatform/flame/FlameAPI.h" -#include "modplatform/modrinth/ModrinthAPI.h" #include "tasks/SequentialTask.h" #include "ui/pages/modplatform/ModModel.h" -#include "ui/pages/modplatform/flame/FlameResourceModels.h" -#include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h" static Version mcVersion(BaseInstance* inst) { @@ -55,14 +51,7 @@ static bool checkDependencies(std::shared_ptr> selected) - : SequentialTask(tr("Get dependencies")) - , m_selected(selected) - , m_flame_provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared(*instance), - std::make_shared() } - , m_modrinth_provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared(*instance), - std::make_shared() } - , m_version(mcVersion(instance)) - , m_loaderType(mcLoaders(instance)) + : SequentialTask(tr("Get dependencies")), m_selected(selected), m_version(mcVersion(instance)), m_loaderType(mcLoaders(instance)) { for (auto mod : folder->allMods()) { m_mods_file_names << mod->fileinfo().fileName(); @@ -144,9 +133,9 @@ QList GetModDependenciesTask::getDependenciesForVersion Task::Ptr GetModDependenciesTask::getProjectInfoTask(std::shared_ptr pDep) { - auto provider = pDep->pack->provider == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; + auto provider = pDep->pack->provider; auto responseInfo = std::make_shared(); - auto info = provider.api->getProject(pDep->pack->addonId.toString(), responseInfo); + auto info = getAPI(provider)->getProject(pDep->pack->addonId.toString(), responseInfo); connect(info.get(), &NetJob::succeeded, [this, responseInfo, provider, pDep] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error); @@ -158,9 +147,10 @@ Task::Ptr GetModDependenciesTask::getProjectInfoTask(std::shared_ptrloadIndexedPack(*pDep->pack, obj); + auto obj = provider == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data") + : Json::requireObject(doc); + + getAPI(provider)->loadIndexedPack(*pDep->pack, obj); } catch (const JSONValidationError& e) { removePack(pDep->pack->addonId); qDebug() << doc; @@ -181,7 +171,8 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen pDep->pack->provider = providerName; m_pack_dependencies.append(pDep); - auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; + + auto provider = providerName; auto tasks = makeShared( QString("DependencyInfo: %1").arg(dep.addonId.toString().isEmpty() ? dep.version : dep.addonId.toString())); @@ -191,46 +182,30 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen } ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType }; - ResourceAPI::DependencySearchCallbacks callbacks; + ResourceAPI::Callback callbacks; callbacks.on_fail = [](QString reason, int) { qCritical() << tr("A network error occurred. Could not load project dependencies:%1").arg(reason); }; - callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, [[maybe_unused]] auto& pack) { - try { - QJsonArray arr; - if (dep.version.length() != 0 && doc.isObject()) { - arr.append(doc.object()); - } else { - arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); - } - pDep->version = provider.mod->loadDependencyVersions(dep, arr); - if (!pDep->version.addonId.isValid()) { - if (m_loaderType & ModPlatform::Quilt) { // falback for quilt - auto overide = ModPlatform::getOverrideDeps(); - auto over = std::find_if(overide.cbegin(), overide.cend(), [dep, provider](const auto& o) { - return o.provider == provider.name && dep.addonId == o.quilt; - }); - if (over != overide.cend()) { - removePack(dep.addonId); - addTask(prepareDependencyTask({ over->fabric, dep.type }, provider.name, level)); - return; - } + callbacks.on_succeed = [dep, provider, pDep, level, this](auto& pack) { + pDep->version = pack; + if (!pDep->version.addonId.isValid()) { + if (m_loaderType & ModPlatform::Quilt) { // falback for quilt + auto overide = ModPlatform::getOverrideDeps(); + auto over = std::find_if(overide.cbegin(), overide.cend(), + [dep, provider](auto o) { return o.provider == provider && dep.addonId == o.quilt; }); + if (over != overide.cend()) { + removePack(dep.addonId); + addTask(prepareDependencyTask({ over->fabric, dep.type }, provider, level)); + return; } - removePack(dep.addonId); - qWarning() << "Error while reading mod version empty "; - qDebug() << doc; - return; } - pDep->version.is_currently_selected = true; - pDep->pack->versions = { pDep->version }; - pDep->pack->versionsLoaded = true; - - } catch (const JSONValidationError& e) { removePack(dep.addonId); - qDebug() << doc; - qWarning() << "Error while reading mod version: " << e.cause(); return; } + pDep->version.is_currently_selected = true; + pDep->pack->versions = { pDep->version }; + pDep->pack->versionsLoaded = true; + if (level == 0) { removePack(dep.addonId); qWarning() << "Dependency cycle exceeded"; @@ -238,10 +213,10 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen } if (dep.addonId.toString().isEmpty() && !pDep->version.addonId.toString().isEmpty()) { pDep->pack->addonId = pDep->version.addonId; - auto dep_ = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider.name); + auto dep_ = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider); if (dep_.addonId != pDep->version.addonId) { removePack(pDep->version.addonId); - addTask(prepareDependencyTask(dep_, provider.name, level)); + addTask(prepareDependencyTask(dep_, provider, level)); } else { addTask(getProjectInfoTask(pDep)); } @@ -250,12 +225,12 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen removePack(pDep->version.addonId); return; } - for (auto dep_ : getDependenciesForVersion(pDep->version, provider.name)) { - addTask(prepareDependencyTask(dep_, provider.name, level - 1)); + for (auto dep_ : getDependenciesForVersion(pDep->version, provider)) { + addTask(prepareDependencyTask(dep_, provider, level - 1)); } }; - auto version = provider.api->getDependencyVersion(std::move(args), std::move(callbacks)); + auto version = getAPI(provider)->getDependencyVersion(std::move(args), std::move(callbacks)); tasks->addTask(version); return tasks; } diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index a02ffb4d5..3530d6cc0 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -28,6 +28,8 @@ #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" +#include "modplatform/flame/FlameAPI.h" +#include "modplatform/modrinth/ModrinthAPI.h" #include "tasks/SequentialTask.h" #include "tasks/Task.h" #include "ui/pages/modplatform/ModModel.h" @@ -54,17 +56,20 @@ class GetModDependenciesTask : public SequentialTask { QStringList required_by; }; - struct Provider { - ModPlatform::ResourceProvider name; - std::shared_ptr mod; - std::shared_ptr api; - }; - explicit GetModDependenciesTask(BaseInstance* instance, ModFolderModel* folder, QList> selected); auto getDependecies() const -> QList> { return m_pack_dependencies; } QHash getExtraInfo(); + private: + inline ResourceAPI* getAPI(ModPlatform::ResourceProvider provider) + { + if (provider == ModPlatform::ResourceProvider::FLAME) + return &m_flameAPI; + else + return &m_modrinthAPI; + } + protected slots: Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, ModPlatform::ResourceProvider, int); QList getDependenciesForVersion(const ModPlatform::IndexedVersion&, @@ -82,9 +87,10 @@ class GetModDependenciesTask : public SequentialTask { QList> m_mods; QList> m_selected; QStringList m_mods_file_names; - Provider m_flame_provider; - Provider m_modrinth_provider; Version m_version; ModPlatform::ModLoaderTypes m_loaderType; + + ModrinthAPI m_modrinthAPI; + FlameAPI m_flameAPI; }; diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 07a256899..6cff8c622 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -128,6 +128,23 @@ struct IndexedVersion { // For internal use, not provided by APIs bool is_currently_selected = false; + + QString getVersionDisplayString() const + { + auto release_type = version_type.isValid() ? QString(" [%1]").arg(version_type.toString()) : ""; + auto versionStr = !version.contains(version_number) ? version_number : ""; + QString gameVersion = ""; + for (auto v : mcVersion) { + if (version.contains(v)) { + gameVersion = ""; + break; + } + if (gameVersion.isEmpty()) { + gameVersion = QObject::tr(" for %1").arg(v); + } + } + return QString("%1%2 — %3%4").arg(version, gameVersion, versionStr, release_type); + } }; struct ExtraPackData { diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/ResourceAPI.cpp similarity index 51% rename from launcher/modplatform/helpers/NetworkResourceAPI.cpp rename to launcher/modplatform/ResourceAPI.cpp index d0e1bb912..448efbc24 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/ResourceAPI.cpp @@ -1,18 +1,14 @@ -// SPDX-FileCopyrightText: 2023 flowln -// -// SPDX-License-Identifier: GPL-3.0-only - -#include "NetworkResourceAPI.h" -#include +#include "modplatform/ResourceAPI.h" #include "Application.h" +#include "Json.h" #include "net/NetJob.h" #include "modplatform/ModIndex.h" #include "net/ApiDownload.h" -Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&& callbacks) const +Task::Ptr ResourceAPI::searchProjects(SearchArgs&& args, Callback>&& callbacks) const { auto search_url_optional = getSearchURL(args); if (!search_url_optional.has_value()) { @@ -40,7 +36,23 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& return; } - callbacks.on_succeed(doc); + QList newList; + auto packs = documentToArray(doc); + + for (auto packRaw : packs) { + auto packObj = packRaw.toObject(); + + ModPlatform::IndexedPack::Ptr pack = std::make_shared(); + try { + loadIndexedPack(*pack, packObj); + newList << pack; + } catch (const JSONValidationError& e) { + qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause(); + continue; + } + } + + callbacks.on_succeed(newList); }); // Capture a weak_ptr instead of a shared_ptr to avoid circular dependency issues. @@ -60,29 +72,7 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& return netJob; } -Task::Ptr NetworkResourceAPI::getProjectInfo(ProjectInfoArgs&& args, ProjectInfoCallbacks&& callbacks) const -{ - auto response = std::make_shared(); - auto job = getProject(args.pack.addonId.toString(), response); - - QObject::connect(job.get(), &NetJob::succeeded, [response, callbacks, args] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset - << " reason: " << parse_error.errorString(); - qWarning() << *response; - return; - } - - callbacks.on_succeed(doc, args.pack); - }); - QObject::connect(job.get(), &NetJob::failed, [callbacks](QString reason) { callbacks.on_fail(reason); }); - QObject::connect(job.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); }); - return job; -} - -Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, VersionSearchCallbacks&& callbacks) const +Task::Ptr ResourceAPI::getProjectVersions(VersionSearchArgs&& args, Callback>&& callbacks) const { auto versions_url_optional = getVersionsURL(args); if (!versions_url_optional.has_value()) @@ -95,7 +85,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response)); - QObject::connect(netJob.get(), &NetJob::succeeded, [response, callbacks, args] { + QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks, args] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -105,7 +95,32 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi return; } - callbacks.on_succeed(doc, args.pack); + QVector unsortedVersions; + try { + auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); + + for (auto versionIter : arr) { + auto obj = versionIter.toObject(); + + auto file = loadIndexedPackVersion(obj, args.resourceType); + if (!file.addonId.isValid()) + file.addonId = args.pack.addonId; + + if (file.fileId.isValid() && !file.downloadUrl.isEmpty()) // Heuristic to check if the returned value is valid + unsortedVersions.append(file); + } + + auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { + // dates are in RFC 3339 format + return a.date > b.date; + }; + std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); + } catch (const JSONValidationError& e) { + qDebug() << doc; + qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause(); + } + + callbacks.on_succeed(unsortedVersions); }); // Capture a weak_ptr instead of a shared_ptr to avoid circular dependency issues. @@ -120,11 +135,147 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi } callbacks.on_fail(reason, network_error_code); }); + QObject::connect(netJob.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); }); return netJob; } -Task::Ptr NetworkResourceAPI::getProject(QString addonId, std::shared_ptr response) const +Task::Ptr ResourceAPI::getProjectInfo(ProjectInfoArgs&& args, Callback&& callbacks) const +{ + auto response = std::make_shared(); + auto job = getProject(args.pack.addonId.toString(), response); + + QObject::connect(job.get(), &NetJob::succeeded, [this, response, callbacks, args] { + auto pack = args.pack; + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + return; + } + try { + auto obj = Json::requireObject(doc); + if (obj.contains("data")) + obj = Json::requireObject(obj, "data"); + loadIndexedPack(pack, obj); + loadExtraPackInfo(pack, obj); + } catch (const JSONValidationError& e) { + qDebug() << doc; + qWarning() << "Error while reading " << debugName() << " resource info: " << e.cause(); + } + callbacks.on_succeed(pack); + }); + // Capture a weak_ptr instead of a shared_ptr to avoid circular dependency issues. + // This prevents the lambda from extending the lifetime of the shared resource, + // as it only temporarily locks the resource when needed. + auto weak = job.toWeakRef(); + QObject::connect(job.get(), &NetJob::failed, [weak, callbacks](const QString& reason) { + int network_error_code = -1; + if (auto job = weak.lock()) { + if (auto netJob = qSharedPointerDynamicCast(job)) { + if (auto* failed_action = netJob->getFailedActions().at(0); failed_action) { + network_error_code = failed_action->replyStatusCode(); + } + } + } + callbacks.on_fail(reason, network_error_code); + }); + QObject::connect(job.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); }); + return job; +} + +Task::Ptr ResourceAPI::getDependencyVersion(DependencySearchArgs&& args, Callback&& callbacks) const +{ + auto versions_url_optional = getDependencyURL(args); + if (!versions_url_optional.has_value()) + return nullptr; + + auto versions_url = versions_url_optional.value(); + + auto netJob = makeShared(QString("%1::Dependency").arg(args.dependency.addonId.toString()), APPLICATION->network()); + auto response = std::make_shared(); + + netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response)); + + QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks, args] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response for getting versions at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + return; + } + + QJsonArray arr; + if (args.dependency.version.length() != 0 && doc.isObject()) { + arr.append(doc.object()); + } else { + arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); + } + + QVector versions; + for (auto versionIter : arr) { + auto obj = versionIter.toObject(); + + auto file = loadIndexedPackVersion(obj, ModPlatform::ResourceType::Mod); + if (!file.addonId.isValid()) + file.addonId = args.dependency.addonId; + + if (file.fileId.isValid() && + (!file.loaders || args.loader & file.loaders)) // Heuristic to check if the returned value is valid + versions.append(file); + } + + auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { + // dates are in RFC 3339 format + return a.date > b.date; + }; + std::sort(versions.begin(), versions.end(), orderSortPredicate); + auto bestMatch = versions.size() != 0 ? versions.front() : ModPlatform::IndexedVersion(); + callbacks.on_succeed(bestMatch); + }); + + // Capture a weak_ptr instead of a shared_ptr to avoid circular dependency issues. + // This prevents the lambda from extending the lifetime of the shared resource, + // as it only temporarily locks the resource when needed. + auto weak = netJob.toWeakRef(); + QObject::connect(netJob.get(), &NetJob::failed, [weak, callbacks](const QString& reason) { + int network_error_code = -1; + if (auto netJob = weak.lock()) { + if (auto* failed_action = netJob->getFailedActions().at(0); failed_action) + network_error_code = failed_action->replyStatusCode(); + } + callbacks.on_fail(reason, network_error_code); + }); + return netJob; +} + +QString ResourceAPI::getGameVersionsString(std::list mcVersions) const +{ + QString s; + for (auto& ver : mcVersions) { + s += QString("\"%1\",").arg(mapMCVersionToModrinth(ver)); + } + s.remove(s.length() - 1, 1); // remove last comma + return s; +} + +QString ResourceAPI::mapMCVersionToModrinth(Version v) const +{ + static const QString preString = " Pre-Release "; + auto verStr = v.toString(); + + if (verStr.contains(preString)) { + verStr.replace(preString, "-pre"); + } + verStr.replace(" ", "-"); + return verStr; +} + +Task::Ptr ResourceAPI::getProject(QString addonId, std::shared_ptr response) const { auto project_url_optional = getInfoURL(addonId); if (!project_url_optional.has_value()) @@ -138,44 +289,3 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, std::shared_ptr(QString("%1::Dependency").arg(args.dependency.addonId.toString()), APPLICATION->network()); - auto response = std::make_shared(); - - netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response)); - - QObject::connect(netJob.get(), &NetJob::succeeded, [response, callbacks, args] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response for getting versions at " << parse_error.offset - << " reason: " << parse_error.errorString(); - qWarning() << *response; - return; - } - - callbacks.on_succeed(doc, args.dependency); - }); - - // Capture a weak_ptr instead of a shared_ptr to avoid circular dependency issues. - // This prevents the lambda from extending the lifetime of the shared resource, - // as it only temporarily locks the resource when needed. - auto weak = netJob.toWeakRef(); - QObject::connect(netJob.get(), &NetJob::failed, [weak, callbacks](const QString& reason) { - int network_error_code = -1; - if (auto netJob = weak.lock()) { - if (auto* failed_action = netJob->getFailedActions().at(0); failed_action) - network_error_code = failed_action->replyStatusCode(); - } - callbacks.on_fail(reason, network_error_code); - }); - return netJob; -} diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 4d40432ee..211a6e477 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -4,7 +4,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2025 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -67,6 +67,13 @@ class ResourceAPI { QString readable_name; }; + template + struct Callback { + std::function on_succeed; + std::function on_fail; + std::function on_abort; + }; + struct SearchArgs { ModPlatform::ResourceType type{}; int offset = 0; @@ -79,31 +86,18 @@ class ResourceAPI { std::optional categoryIds; bool openSource; }; - struct SearchCallbacks { - std::function on_succeed; - std::function on_fail; - std::function on_abort; - }; struct VersionSearchArgs { ModPlatform::IndexedPack pack; std::optional> mcVersions; std::optional loaders; - }; - struct VersionSearchCallbacks { - std::function on_succeed; - std::function on_fail; + ModPlatform::ResourceType resourceType; }; struct ProjectInfoArgs { ModPlatform::IndexedPack pack; }; - struct ProjectInfoCallbacks { - std::function on_succeed; - std::function on_fail; - std::function on_abort; - }; struct DependencySearchArgs { ModPlatform::Dependency dependency; @@ -111,73 +105,52 @@ class ResourceAPI { ModPlatform::ModLoaderTypes loader; }; - struct DependencySearchCallbacks { - std::function on_succeed; - std::function on_fail; - }; - public: /** Gets a list of available sorting methods for this API. */ virtual auto getSortingMethods() const -> QList = 0; public slots: - [[nodiscard]] virtual Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&&) const - { - qWarning() << "TODO: ResourceAPI::searchProjects"; - return nullptr; - } - virtual Task::Ptr getProject([[maybe_unused]] QString addonId, - [[maybe_unused]] std::shared_ptr response) const - { - qWarning() << "TODO: ResourceAPI::getProject"; - return nullptr; - } - virtual Task::Ptr getProjects([[maybe_unused]] QStringList addonIds, - [[maybe_unused]] std::shared_ptr response) const - { - qWarning() << "TODO: ResourceAPI::getProjects"; - return nullptr; - } + virtual Task::Ptr searchProjects(SearchArgs&&, Callback>&&) const; - virtual Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const - { - qWarning() << "TODO: ResourceAPI::getProjectInfo"; - return nullptr; - } - virtual Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const - { - qWarning() << "TODO: ResourceAPI::getProjectVersions"; - return nullptr; - } + virtual Task::Ptr getProject(QString addonId, std::shared_ptr response) const; + virtual Task::Ptr getProjects(QStringList addonIds, std::shared_ptr response) const = 0; - virtual Task::Ptr getDependencyVersion(DependencySearchArgs&&, DependencySearchCallbacks&&) const - { - qWarning() << "TODO"; - return nullptr; - } + virtual Task::Ptr getProjectInfo(ProjectInfoArgs&&, Callback&&) const; + Task::Ptr getProjectVersions(VersionSearchArgs&& args, Callback>&& callbacks) const; + virtual Task::Ptr getDependencyVersion(DependencySearchArgs&&, Callback&&) const; protected: inline QString debugName() const { return "External resource API"; } - inline QString mapMCVersionToModrinth(Version v) const - { - static const QString preString = " Pre-Release "; - auto verStr = v.toString(); + QString mapMCVersionToModrinth(Version v) const; - if (verStr.contains(preString)) { - verStr.replace(preString, "-pre"); - } - verStr.replace(" ", "-"); - return verStr; - } + QString getGameVersionsString(std::list mcVersions) const; - inline QString getGameVersionsString(std::list mcVersions) const - { - QString s; - for (auto& ver : mcVersions) { - s += QString("\"%1\",").arg(mapMCVersionToModrinth(ver)); - } - s.remove(s.length() - 1, 1); // remove last comma - return s; - } + public: + virtual auto getSearchURL(SearchArgs const& args) const -> std::optional = 0; + virtual auto getInfoURL(QString const& id) const -> std::optional = 0; + virtual auto getVersionsURL(VersionSearchArgs const& args) const -> std::optional = 0; + virtual auto getDependencyURL(DependencySearchArgs const& args) const -> std::optional = 0; + + /** Functions to load data into a pack. + * + * Those are needed for the same reason as documentToArray, and NEED to be re-implemented in the same way. + */ + + virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) const = 0; + virtual ModPlatform::IndexedVersion loadIndexedPackVersion(QJsonObject& obj, ModPlatform::ResourceType) const = 0; + + /** Converts a JSON document to a common array format. + * + * This is needed so that different providers, with different JSON structures, can be parsed + * uniformally. You NEED to re-implement this if you intend on using the default callbacks. + */ + virtual QJsonArray documentToArray(QJsonDocument& obj) const = 0; + + /** Functions to load data into a pack. + * + * Those are needed for the same reason as documentToArray, and NEED to be re-implemented in the same way. + */ + + virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) const = 0; }; diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 1e39ca994..799e142ce 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -7,11 +7,13 @@ #include #include #include "BuildConfig.h" +#include "Json.h" +#include "Version.h" #include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" -#include "modplatform/helpers/NetworkResourceAPI.h" +#include "modplatform/flame/FlameModIndex.h" -class FlameAPI : public NetworkResourceAPI { +class FlameAPI : public ResourceAPI { public: QString getModFileChangelog(int modId, int fileId); QString getModDescription(int modId); @@ -138,6 +140,25 @@ class FlameAPI : public NetworkResourceAPI { return url; } + QJsonArray documentToArray(QJsonDocument& obj) const override { return Json::ensureArray(obj.object(), "data"); } + void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) const override { FlameMod::loadIndexedPack(m, obj); } + ModPlatform::IndexedVersion loadIndexedPackVersion(QJsonObject& obj, ModPlatform::ResourceType resourceType) const override + { + auto arr = FlameMod::loadIndexedPackVersion(obj); + if (resourceType != ModPlatform::ResourceType::TexturePack) { + return arr; + } + // FIXME: Client-side version filtering. This won't take into account any user-selected filtering. + auto const& mc_versions = arr.mcVersion; + + if (std::any_of(mc_versions.constBegin(), mc_versions.constEnd(), + [](auto const& mc_version) { return Version(mc_version) <= Version("1.6"); })) { + return arr; + } + return {}; + }; + void loadExtraPackInfo(ModPlatform::IndexedPack& m, [[maybe_unused]] QJsonObject&) const override { FlameMod::loadBody(m); } + private: std::optional getInfoURL(QString const& id) const override { diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 660dc159c..d92ee729c 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -58,7 +58,7 @@ void FlameMod::loadURLs(ModPlatform::IndexedPack& pack, QJsonObject& obj) pack.extraDataLoaded = true; } -void FlameMod::loadBody(ModPlatform::IndexedPack& pack, [[maybe_unused]] QJsonObject& obj) +void FlameMod::loadBody(ModPlatform::IndexedPack& pack) { pack.extraData.body = api.getModDescription(pack.addonId.toInt()); @@ -204,31 +204,3 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> return file; } - -ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst) -{ - auto profile = (dynamic_cast(inst))->getPackProfile(); - QString mcVersion = profile->getComponentVersion("net.minecraft"); - auto loaders = profile->getSupportedModLoaders(); - QList versions; - for (auto versionIter : arr) { - auto obj = versionIter.toObject(); - - auto file = loadIndexedPackVersion(obj); - if (!file.addonId.isValid()) - file.addonId = m.addonId; - - if (file.fileId.isValid() && - (!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid - versions.append(file); - } - - auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - // dates are in RFC 3339 format - return a.date > b.date; - }; - std::sort(versions.begin(), versions.end(), orderSortPredicate); - if (versions.size() != 0) - return versions.front(); - return {}; -} diff --git a/launcher/modplatform/flame/FlameModIndex.h b/launcher/modplatform/flame/FlameModIndex.h index f6b4b22be..b583b518f 100644 --- a/launcher/modplatform/flame/FlameModIndex.h +++ b/launcher/modplatform/flame/FlameModIndex.h @@ -12,8 +12,7 @@ namespace FlameMod { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj); void loadURLs(ModPlatform::IndexedPack& m, QJsonObject& obj); -void loadBody(ModPlatform::IndexedPack& m, QJsonObject& obj); +void loadBody(ModPlatform::IndexedPack& m); void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr); ModPlatform::IndexedVersion loadIndexedPackVersion(QJsonObject& obj, bool load_changelog = false); -ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst); } // namespace FlameMod \ No newline at end of file diff --git a/launcher/modplatform/flame/FlamePackIndex.cpp b/launcher/modplatform/flame/FlamePackIndex.cpp deleted file mode 100644 index db2061d99..000000000 --- a/launcher/modplatform/flame/FlamePackIndex.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "FlamePackIndex.h" -#include -#include - -#include "Json.h" -#include "modplatform/ModIndex.h" - -void Flame::loadIndexedPack(Flame::IndexedPack& pack, QJsonObject& obj) -{ - pack.addonId = Json::requireInteger(obj, "id"); - pack.name = Json::requireString(obj, "name"); - pack.description = Json::ensureString(obj, "summary", ""); - - auto logo = Json::requireObject(obj, "logo"); - pack.logoUrl = Json::requireString(logo, "thumbnailUrl"); - pack.logoName = Json::requireString(obj, "slug") + "." + QFileInfo(QUrl(pack.logoUrl).fileName()).suffix(); - - 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, "mainFileId"); - - 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, "gameVersions"); - if (versionArray.size() < 1) { - continue; - } - - found = true; - break; - } - if (!found) { - throw JSONValidationError(QString("Pack with no good file, skipping: %1").arg(pack.name)); - } - - loadIndexedInfo(pack, obj); -} - -void Flame::loadIndexedInfo(IndexedPack& pack, QJsonObject& obj) -{ - auto links_obj = Json::ensureObject(obj, "links"); - - pack.extra.websiteUrl = Json::ensureString(links_obj, "websiteUrl"); - if (pack.extra.websiteUrl.endsWith('/')) - pack.extra.websiteUrl.chop(1); - - pack.extra.issuesUrl = Json::ensureString(links_obj, "issuesUrl"); - if (pack.extra.issuesUrl.endsWith('/')) - pack.extra.issuesUrl.chop(1); - - pack.extra.sourceUrl = Json::ensureString(links_obj, "sourceUrl"); - if (pack.extra.sourceUrl.endsWith('/')) - pack.extra.sourceUrl.chop(1); - - pack.extra.wikiUrl = Json::ensureString(links_obj, "wikiUrl"); - if (pack.extra.wikiUrl.endsWith('/')) - pack.extra.wikiUrl.chop(1); - - pack.extraInfoLoaded = true; -} - -void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr) -{ - QList 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, "gameVersions"); - if (versionArray.size() < 1) { - continue; - } - - for (auto mcVer : versionArray) { - auto str = mcVer.toString(); - - if (str.contains('.')) - file.mcVersion.append(str); - - if (auto loader = str.toLower(); loader == "neoforge") - file.loaders |= ModPlatform::NeoForge; - else if (loader == "forge") - file.loaders |= ModPlatform::Forge; - else if (loader == "cauldron") - file.loaders |= ModPlatform::Cauldron; - else if (loader == "liteloader") - file.loaders |= ModPlatform::LiteLoader; - else if (loader == "fabric") - file.loaders |= ModPlatform::Fabric; - else if (loader == "quilt") - file.loaders |= ModPlatform::Quilt; - } - - // pick the latest version supported - file.version = Json::requireString(version, "displayName"); - - ModPlatform::IndexedVersionType::VersionType ver_type; - switch (Json::requireInteger(version, "releaseType")) { - case 1: - ver_type = ModPlatform::IndexedVersionType::VersionType::Release; - break; - case 2: - ver_type = ModPlatform::IndexedVersionType::VersionType::Beta; - break; - case 3: - ver_type = ModPlatform::IndexedVersionType::VersionType::Alpha; - break; - default: - ver_type = ModPlatform::IndexedVersionType::VersionType::Unknown; - } - file.version_type = ModPlatform::IndexedVersionType(ver_type); - file.downloadUrl = Json::ensureString(version, "downloadUrl"); - - // only add if we have a download URL (third party distribution is enabled) - if (!file.downloadUrl.isEmpty()) { - 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; -} - -auto Flame::getVersionDisplayString(const IndexedVersion& version) -> QString -{ - auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : ""; - auto mcVersion = - !version.mcVersion.isEmpty() && !version.version.contains(version.mcVersion) ? QObject::tr(" for %1").arg(version.mcVersion) : ""; - return QString("%1%2%3").arg(version.version, mcVersion, release_type); -} diff --git a/launcher/modplatform/flame/FlamePackIndex.h b/launcher/modplatform/flame/FlamePackIndex.h deleted file mode 100644 index 22f7d648a..000000000 --- a/launcher/modplatform/flame/FlamePackIndex.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include -#include -#include -#include "modplatform/ModIndex.h" - -namespace Flame { - -struct ModpackAuthor { - QString name; - QString url; -}; - -struct IndexedVersion { - int addonId; - int fileId; - QString version; - ModPlatform::IndexedVersionType version_type; - ModPlatform::ModLoaderTypes loaders = {}; - QString mcVersion; - QString downloadUrl; -}; - -struct ModpackExtra { - QString websiteUrl; - QString wikiUrl; - QString issuesUrl; - QString sourceUrl; -}; - -struct IndexedPack { - int addonId; - QString name; - QString description; - QList authors; - QString logoName; - QString logoUrl; - - bool versionsLoaded = false; - QList versions; - - bool extraInfoLoaded = false; - ModpackExtra extra; -}; - -void loadIndexedPack(IndexedPack& m, QJsonObject& obj); -void loadIndexedInfo(IndexedPack&, QJsonObject&); -void loadIndexedPackVersions(IndexedPack& m, QJsonArray& arr); - -auto getVersionDisplayString(const IndexedVersion&) -> QString; -} // namespace Flame - -Q_DECLARE_METATYPE(Flame::IndexedPack) -Q_DECLARE_METATYPE(QList) diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.h b/launcher/modplatform/helpers/NetworkResourceAPI.h deleted file mode 100644 index d89014a38..000000000 --- a/launcher/modplatform/helpers/NetworkResourceAPI.h +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: 2023 flowln -// -// SPDX-License-Identifier: GPL-3.0-only - -#pragma once - -#include -#include "modplatform/ResourceAPI.h" - -class NetworkResourceAPI : public ResourceAPI { - public: - Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&&) const override; - - Task::Ptr getProject(QString addonId, std::shared_ptr response) const override; - - Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const override; - Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const override; - Task::Ptr getDependencyVersion(DependencySearchArgs&&, DependencySearchCallbacks&&) const override; - - protected: - virtual auto getSearchURL(SearchArgs const& args) const -> std::optional = 0; - virtual auto getInfoURL(QString const& id) const -> std::optional = 0; - virtual auto getVersionsURL(VersionSearchArgs const& args) const -> std::optional = 0; - virtual auto getDependencyURL(DependencySearchArgs const& args) const -> std::optional = 0; -}; diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 5b426a06a..c2714b3c8 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -5,12 +5,14 @@ #pragma once #include "BuildConfig.h" +#include "Json.h" #include "modplatform/ModIndex.h" -#include "modplatform/helpers/NetworkResourceAPI.h" +#include "modplatform/ResourceAPI.h" +#include "modplatform/modrinth/ModrinthPackIndex.h" #include -class ModrinthAPI : public NetworkResourceAPI { +class ModrinthAPI : public ResourceAPI { public: Task::Ptr currentVersion(QString hash, QString hash_format, std::shared_ptr response); @@ -214,4 +216,12 @@ class ModrinthAPI : public NetworkResourceAPI { .arg(mapMCVersionToModrinth(args.mcVersion)) .arg(getModLoaderStrings(args.loader).join("\",\"")); }; + + QJsonArray documentToArray(QJsonDocument& obj) const override { return obj.object().value("hits").toArray(); } + void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) const override { Modrinth::loadIndexedPack(m, obj); } + ModPlatform::IndexedVersion loadIndexedPackVersion(QJsonObject& obj, ModPlatform::ResourceType) const override + { + return Modrinth::loadIndexedPackVersion(obj); + }; + void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) const override { Modrinth::loadExtraPackData(m, obj); } }; diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 374b7681e..18b435106 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -13,7 +13,6 @@ #include "modplatform/EnsureMetadataTask.h" #include "modplatform/helpers/OverrideUtils.h" -#include "modplatform/modrinth/ModrinthPackManifest.h" #include "net/ChecksumValidator.h" #include "net/ApiDownload.h" @@ -85,7 +84,7 @@ bool ModrinthCreationTask::updateInstance() QString old_index_path(FS::PathCombine(old_index_folder, "modrinth.index.json")); QFileInfo old_index_file(old_index_path); if (old_index_file.exists()) { - std::vector old_files; + std::vector old_files; parseManifest(old_index_path, old_files, false, false); // Let's remove all duplicated, identical resources! @@ -356,7 +355,7 @@ bool ModrinthCreationTask::createInstance() } bool ModrinthCreationTask::parseManifest(const QString& index_path, - std::vector& files, + std::vector& files, bool set_internal_data, bool show_optional_dialog) { @@ -377,9 +376,9 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, } auto jsonFiles = Json::requireIsArrayOf(obj, "files", "modrinth.index.json"); - std::vector optionalFiles; + std::vector optionalFiles; for (const auto& modInfo : jsonFiles) { - Modrinth::File file; + File file; file.path = Json::requireString(modInfo, "path").replace("\\", "/"); auto env = Json::ensureObject(modInfo, "env"); diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h index ddfa7ae95..e02a55877 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h @@ -1,13 +1,27 @@ #pragma once #include + +#include +#include +#include +#include +#include +#include + #include "BaseInstance.h" #include "InstanceCreationTask.h" -#include "modplatform/modrinth/ModrinthPackManifest.h" - class ModrinthCreationTask final : public InstanceCreationTask { Q_OBJECT + struct File { + QString path; + + QCryptographicHash::Algorithm hashAlgorithm; + QByteArray hash; + QQueue downloads; + bool required = true; + }; public: ModrinthCreationTask(QString staging_path, @@ -30,7 +44,7 @@ class ModrinthCreationTask final : public InstanceCreationTask { bool createInstance() override; private: - bool parseManifest(const QString&, std::vector&, bool set_internal_data = true, bool show_optional_dialog = true); + bool parseManifest(const QString&, std::vector&, bool set_internal_data = true, bool show_optional_dialog = true); private: QWidget* m_parent = nullptr; @@ -38,7 +52,7 @@ class ModrinthCreationTask final : public InstanceCreationTask { QString m_minecraft_version, m_fabric_version, m_quilt_version, m_forge_version, m_neoForge_version; QString m_managed_id, m_managed_version_id, m_managed_name; - std::vector m_files; + std::vector m_files; Task::Ptr m_task; std::optional m_instance; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 42fda9df1..8e0552a48 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -112,25 +112,6 @@ void Modrinth::loadExtraPackData(ModPlatform::IndexedPack& pack, QJsonObject& ob pack.extraDataLoaded = true; } -void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr) -{ - QList unsortedVersions; - for (auto versionIter : arr) { - auto obj = versionIter.toObject(); - auto file = loadIndexedPackVersion(obj); - - if (file.fileId.isValid()) // Heuristic to check if the returned value is valid - unsortedVersions.append(file); - } - auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - // dates are in RFC 3339 format - return a.date > b.date; - }; - std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); - pack.versions = unsortedVersions; - pack.versionsLoaded = true; -} - ModPlatform::IndexedVersion Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_type, QString preferred_file_name) { ModPlatform::IndexedVersion file; @@ -244,28 +225,3 @@ ModPlatform::IndexedVersion Modrinth::loadIndexedPackVersion(QJsonObject& obj, Q return {}; } - -ModPlatform::IndexedVersion Modrinth::loadDependencyVersions([[maybe_unused]] const ModPlatform::Dependency& m, - QJsonArray& arr, - const BaseInstance* inst) -{ - auto profile = (dynamic_cast(inst))->getPackProfile(); - QString mcVersion = profile->getComponentVersion("net.minecraft"); - auto loaders = profile->getSupportedModLoaders(); - - QList versions; - for (auto versionIter : arr) { - auto obj = versionIter.toObject(); - auto file = loadIndexedPackVersion(obj); - - if (file.fileId.isValid() && - (!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid - versions.append(file); - } - auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - // dates are in RFC 3339 format - return a.date > b.date; - }; - std::sort(versions.begin(), versions.end(), orderSortPredicate); - return versions.length() != 0 ? versions.front() : ModPlatform::IndexedVersion(); -} diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.h b/launcher/modplatform/modrinth/ModrinthPackIndex.h index 16f3d262c..5d852cb6f 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.h +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.h @@ -25,8 +25,6 @@ namespace Modrinth { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj); void loadExtraPackData(ModPlatform::IndexedPack& m, QJsonObject& obj); -void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr); auto loadIndexedPackVersion(QJsonObject& obj, QString hash_type = "sha512", QString filename_prefer = "") -> ModPlatform::IndexedVersion; -auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst) -> ModPlatform::IndexedVersion; } // namespace Modrinth diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp deleted file mode 100644 index 1e90f713e..000000000 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2022 flowln - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright 2013-2021 MultiMC Contributors - * Copyright 2022 kb1000 - * - * 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 "ModrinthPackManifest.h" -#include -#include "Json.h" - -#include "modplatform/modrinth/ModrinthAPI.h" - -#include - -static ModrinthAPI api; - -namespace Modrinth { - -void loadIndexedPack(Modpack& pack, QJsonObject& obj) -{ - pack.id = Json::ensureString(obj, "project_id"); - - pack.name = Json::ensureString(obj, "title"); - pack.description = Json::ensureString(obj, "description"); - auto temp_author_name = Json::ensureString(obj, "author"); - pack.author = std::make_tuple(temp_author_name, api.getAuthorURL(temp_author_name)); - pack.iconUrl = Json::ensureString(obj, "icon_url"); - pack.iconName = QString("modrinth_%1.%2").arg(Json::ensureString(obj, "slug"), QFileInfo(pack.iconUrl.fileName()).suffix()); -} - -void loadIndexedInfo(Modpack& pack, QJsonObject& obj) -{ - pack.extra.body = Json::ensureString(obj, "body"); - pack.extra.projectUrl = QString("https://modrinth.com/modpack/%1").arg(Json::ensureString(obj, "slug")); - - pack.extra.issuesUrl = Json::ensureString(obj, "issues_url"); - if (pack.extra.issuesUrl.endsWith('/')) - pack.extra.issuesUrl.chop(1); - - pack.extra.sourceUrl = Json::ensureString(obj, "source_url"); - if (pack.extra.sourceUrl.endsWith('/')) - pack.extra.sourceUrl.chop(1); - - pack.extra.wikiUrl = Json::ensureString(obj, "wiki_url"); - if (pack.extra.wikiUrl.endsWith('/')) - pack.extra.wikiUrl.chop(1); - - pack.extra.discordUrl = Json::ensureString(obj, "discord_url"); - if (pack.extra.discordUrl.endsWith('/')) - pack.extra.discordUrl.chop(1); - - auto donate_arr = Json::ensureArray(obj, "donation_urls"); - for (auto d : donate_arr) { - auto d_obj = Json::requireObject(d); - - DonationData donate; - - donate.id = Json::ensureString(d_obj, "id"); - donate.platform = Json::ensureString(d_obj, "platform"); - donate.url = Json::ensureString(d_obj, "url"); - - pack.extra.donate.append(donate); - } - - pack.extra.status = Json::ensureString(obj, "status"); - - pack.extraInfoLoaded = true; -} - -void loadIndexedVersions(Modpack& pack, QJsonDocument& doc) -{ - QList unsortedVersions; - - auto arr = Json::requireArray(doc); - - for (auto versionIter : arr) { - auto obj = Json::requireObject(versionIter); - auto file = loadIndexedVersion(obj); - - if (!file.id.isEmpty()) // Heuristic to check if the returned value is valid - unsortedVersions.append(file); - } - auto orderSortPredicate = [](const ModpackVersion& a, const ModpackVersion& b) -> bool { - // dates are in RFC 3339 format - return a.date > b.date; - }; - - std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); - - pack.versions.swap(unsortedVersions); - - pack.versionsLoaded = true; -} - -auto loadIndexedVersion(QJsonObject& obj) -> ModpackVersion -{ - ModpackVersion file; - - file.name = Json::requireString(obj, "name"); - file.version = Json::requireString(obj, "version_number"); - auto gameVersions = Json::ensureArray(obj, "game_versions"); - if (!gameVersions.isEmpty()) { - file.gameVersion = Json::ensureString(gameVersions[0]); - file.gameVersion = ModrinthAPI::mapMCVersionFromModrinth(file.gameVersion); - } - auto loaders = Json::requireArray(obj, "loaders"); - for (auto loader : loaders) { - if (loader == "neoforge") - file.loaders |= ModPlatform::NeoForge; - else if (loader == "forge") - file.loaders |= ModPlatform::Forge; - else if (loader == "cauldron") - file.loaders |= ModPlatform::Cauldron; - else if (loader == "liteloader") - file.loaders |= ModPlatform::LiteLoader; - else if (loader == "fabric") - file.loaders |= ModPlatform::Fabric; - else if (loader == "quilt") - file.loaders |= ModPlatform::Quilt; - } - file.version_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type")); - file.changelog = Json::ensureString(obj, "changelog"); - - file.id = Json::requireString(obj, "id"); - file.project_id = Json::requireString(obj, "project_id"); - - file.date = Json::requireString(obj, "date_published"); - - auto files = Json::requireArray(obj, "files"); - - for (auto file_iter : files) { - File indexed_file; - auto parent = Json::requireObject(file_iter); - auto is_primary = Json::ensureBoolean(parent, (const QString)QStringLiteral("primary"), false); - if (!is_primary) { - auto filename = Json::ensureString(parent, "filename"); - // Checking suffix here is fine because it's the response from Modrinth, - // so one would assume it will always be in English. - if (!filename.endsWith("mrpack") && !filename.endsWith("zip")) - continue; - } - - auto url = Json::requireString(parent, "url"); - - file.download_url = url; - if (is_primary) - break; - } - - if (file.download_url.isEmpty()) - return {}; - - return file; -} - -auto getVersionDisplayString(const ModpackVersion& version) -> QString -{ - auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : ""; - auto mcVersion = !version.gameVersion.isEmpty() && !version.name.contains(version.gameVersion) - ? QObject::tr(" for %1").arg(version.gameVersion) - : ""; - auto versionStr = !version.name.contains(version.version) ? version.version : ""; - return QString("%1%2 — %3%4").arg(version.name, mcVersion, versionStr, release_type); -} - -} // namespace Modrinth diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.h b/launcher/modplatform/modrinth/ModrinthPackManifest.h deleted file mode 100644 index a990e9a77..000000000 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.h +++ /dev/null @@ -1,129 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2022 flowln - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright 2013-2021 MultiMC Contributors - * Copyright 2022 kb1000 - * - * 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 -#include - -#include "modplatform/ModIndex.h" - -class MinecraftInstance; - -namespace Modrinth { - -struct File { - QString path; - - QCryptographicHash::Algorithm hashAlgorithm; - QByteArray hash; - QQueue downloads; - bool required = true; -}; - -struct DonationData { - QString id; - QString platform; - QString url; -}; - -struct ModpackExtra { - QString body; - - QString projectUrl; - - QString issuesUrl; - QString sourceUrl; - QString wikiUrl; - QString discordUrl; - - QList donate; - - QString status; -}; - -struct ModpackVersion { - QString name; - QString version; - QString gameVersion; - ModPlatform::IndexedVersionType version_type; - QString changelog; - ModPlatform::ModLoaderTypes loaders = {}; - - QString id; - QString project_id; - - QString date; - - QString download_url; -}; - -struct Modpack { - QString id; - - QString name; - QString description; - std::tuple author; - QString iconName; - QUrl iconUrl; - - bool versionsLoaded = false; - bool extraInfoLoaded = false; - - ModpackExtra extra; - QList versions; -}; - -void loadIndexedPack(Modpack&, QJsonObject&); -void loadIndexedInfo(Modpack&, QJsonObject&); -void loadIndexedVersions(Modpack&, QJsonDocument&); -auto loadIndexedVersion(QJsonObject&) -> ModpackVersion; - -auto validateDownloadUrl(QUrl) -> bool; - -auto getVersionDisplayString(const ModpackVersion&) -> QString; - -} // namespace Modrinth - -Q_DECLARE_METATYPE(Modrinth::Modpack) -Q_DECLARE_METATYPE(Modrinth::ModpackVersion) -Q_DECLARE_METATYPE(QList) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 01bc6c2fd..d46f0f8d5 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -22,8 +22,6 @@ #include "Markdown.h" #include "StringUtils.h" -#include "modplatform/modrinth/ModrinthPackManifest.h" - #include "ui/InstanceWindow.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" @@ -256,36 +254,13 @@ void ModrinthManagedPackPage::parseManagedPack() if (m_fetch_job && m_fetch_job->isRunning()) m_fetch_job->abort(); - m_fetch_job.reset(new NetJob(QString("Modrinth::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network())); - auto response = std::make_shared(); + ResourceAPI::Callback> callbacks{}; + m_pack = { m_inst->getManagedPackID() }; - QString id = m_inst->getManagedPackID(); - - m_fetch_job->addNetAction( - Net::ApiDownload::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); - - connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Modrinth at " << parse_error.offset - << " reason: " << parse_error.errorString(); - qWarning() << *response; - - setFailState(); - - return; - } - - try { - Modrinth::loadIndexedVersions(m_pack, doc); - } catch (const JSONValidationError& e) { - qDebug() << *response; - qWarning() << "Error while reading modrinth modpack version: " << e.cause(); - - setFailState(); - return; - } + // Use default if no callbacks are set + callbacks.on_succeed = [this](auto& doc) { + m_pack.versions = doc; + m_pack.versionsLoaded = true; // We block signals here so that suggestVersion() doesn't get called, causing an assertion fail. ui->versionsComboBox->blockSignals(true); @@ -293,22 +268,23 @@ void ModrinthManagedPackPage::parseManagedPack() ui->versionsComboBox->blockSignals(false); for (const auto& version : m_pack.versions) { - QString name = Modrinth::getVersionDisplayString(version); + QString name = version.getVersionDisplayString(); // NOTE: the id from version isn't the same id in the modpack format spec... // e.g. HexMC's 4.4.0 has versionId 4.0.0 in the modpack index.............. if (version.version == m_inst->getManagedPackVersionName()) name = tr("%1 (Current)").arg(name); - ui->versionsComboBox->addItem(name, QVariant(version.id)); + ui->versionsComboBox->addItem(name, version.fileId); } suggestVersion(); m_loaded = true; - }); - connect(m_fetch_job.get(), &NetJob::failed, this, &ModrinthManagedPackPage::setFailState); - connect(m_fetch_job.get(), &NetJob::aborted, this, &ModrinthManagedPackPage::setFailState); + }; + callbacks.on_fail = [this](QString reason, int) { setFailState(); }; + callbacks.on_abort = [this]() { setFailState(); }; + m_fetch_job = m_api.getProjectVersions({ m_pack, {}, {}, ModPlatform::ResourceType::Modpack }, std::move(callbacks)); ui->changelogTextBrowser->setText(tr("Fetching changelogs...")); @@ -370,10 +346,10 @@ void ModrinthManagedPackPage::update() QMap extra_info; // NOTE: Don't use 'm_pack.id' here, since we didn't completely parse all the metadata for the pack, including this field. extra_info.insert("pack_id", m_inst->getManagedPackID()); - extra_info.insert("pack_version_id", version.id); + extra_info.insert("pack_version_id", version.fileId.toString()); extra_info.insert("original_instance_id", m_inst->id()); - auto extracted = new InstanceImportTask(version.download_url, this, std::move(extra_info)); + auto extracted = new InstanceImportTask(version.downloadUrl, this, std::move(extra_info)); InstanceName inst_name(m_inst->getManagedPackName(), version.version); inst_name.setName(m_inst->name().replace(m_inst->getManagedPackVersionName(), version.version)); @@ -449,37 +425,15 @@ void FlameManagedPackPage::parseManagedPack() if (m_fetch_job && m_fetch_job->isRunning()) m_fetch_job->abort(); - m_fetch_job.reset(new NetJob(QString("Flame::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network())); - auto response = std::make_shared(); - QString id = m_inst->getManagedPackID(); + m_pack = { id }; - m_fetch_job->addNetAction(Net::ApiDownload::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response)); + ResourceAPI::Callback> callbacks{}; - connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Flame at " << parse_error.offset - << " reason: " << parse_error.errorString(); - qWarning() << *response; - - setFailState(); - - return; - } - - try { - auto obj = doc.object(); - auto data = Json::ensureArray(obj, "data"); - Flame::loadIndexedPackVersions(m_pack, data); - } catch (const JSONValidationError& e) { - qDebug() << *response; - qWarning() << "Error while reading flame modpack version: " << e.cause(); - - setFailState(); - return; - } + // Use default if no callbacks are set + callbacks.on_succeed = [this](auto& doc) { + m_pack.versions = doc; + m_pack.versionsLoaded = true; // We block signals here so that suggestVersion() doesn't get called, causing an assertion fail. ui->versionsComboBox->blockSignals(true); @@ -487,7 +441,7 @@ void FlameManagedPackPage::parseManagedPack() ui->versionsComboBox->blockSignals(false); for (const auto& version : m_pack.versions) { - QString name = Flame::getVersionDisplayString(version); + QString name = version.getVersionDisplayString(); if (version.fileId == m_inst->getManagedPackVersionID().toInt()) name = tr("%1 (Current)").arg(name); @@ -498,9 +452,10 @@ void FlameManagedPackPage::parseManagedPack() suggestVersion(); m_loaded = true; - }); - connect(m_fetch_job.get(), &NetJob::failed, this, &FlameManagedPackPage::setFailState); - connect(m_fetch_job.get(), &NetJob::aborted, this, &FlameManagedPackPage::setFailState); + }; + callbacks.on_fail = [this](QString reason, int) { setFailState(); }; + callbacks.on_abort = [this]() { setFailState(); }; + m_fetch_job = m_api.getProjectVersions({ m_pack, {}, {}, ModPlatform::ResourceType::Modpack }, std::move(callbacks)); m_fetch_job->start(); } @@ -521,7 +476,7 @@ void FlameManagedPackPage::suggestVersion() auto version = m_pack.versions.at(index); ui->changelogTextBrowser->setHtml( - StringUtils::htmlListPatch(m_api.getModFileChangelog(m_inst->getManagedPackID().toInt(), version.fileId))); + StringUtils::htmlListPatch(m_api.getModFileChangelog(m_inst->getManagedPackID().toInt(), version.fileId.toInt()))); ManagedPackPage::suggestVersion(); } @@ -537,7 +492,7 @@ void FlameManagedPackPage::update() QMap extra_info; extra_info.insert("pack_id", m_inst->getManagedPackID()); - extra_info.insert("pack_version_id", QString::number(version.fileId)); + extra_info.insert("pack_version_id", version.fileId.toString()); extra_info.insert("original_instance_id", m_inst->id()); auto extracted = new InstanceImportTask(version.downloadUrl, this, std::move(extra_info)); diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index 966c57768..f319ed069 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -6,11 +6,10 @@ #include "BaseInstance.h" +#include "modplatform/ModIndex.h" #include "modplatform/modrinth/ModrinthAPI.h" -#include "modplatform/modrinth/ModrinthPackManifest.h" #include "modplatform/flame/FlameAPI.h" -#include "modplatform/flame/FlamePackIndex.h" #include "net/NetJob.h" @@ -130,9 +129,9 @@ class ModrinthManagedPackPage final : public ManagedPackPage { void updateFromFile() override; private: - NetJob::Ptr m_fetch_job = nullptr; + Task::Ptr m_fetch_job = nullptr; - Modrinth::Modpack m_pack; + ModPlatform::IndexedPack m_pack; ModrinthAPI m_api; }; @@ -154,8 +153,8 @@ class FlameManagedPackPage final : public ManagedPackPage { void updateFromFile() override; private: - NetJob::Ptr m_fetch_job = nullptr; + Task::Ptr m_fetch_job = nullptr; - Flame::IndexedPack m_pack; + ModPlatform::IndexedPack m_pack; FlameAPI m_api; }; diff --git a/launcher/ui/pages/modplatform/DataPackModel.cpp b/launcher/ui/pages/modplatform/DataPackModel.cpp index 547f0a363..846ef5aa4 100644 --- a/launcher/ui/pages/modplatform/DataPackModel.cpp +++ b/launcher/ui/pages/modplatform/DataPackModel.cpp @@ -9,8 +9,8 @@ namespace ResourceDownload { -DataPackResourceModel::DataPackResourceModel(BaseInstance const& base_inst, ResourceAPI* api) - : ResourceModel(api), m_base_instance(base_inst) +DataPackResourceModel::DataPackResourceModel(BaseInstance const& base_inst, ResourceAPI* api, QString debugName, QString metaEntryBase) + : ResourceModel(api), m_base_instance(base_inst), m_debugName(debugName + " (Model)"), m_metaEntryBase(metaEntryBase) {} /******** Make data requests ********/ diff --git a/launcher/ui/pages/modplatform/DataPackModel.h b/launcher/ui/pages/modplatform/DataPackModel.h index 89e83969c..29b11ffd6 100644 --- a/launcher/ui/pages/modplatform/DataPackModel.h +++ b/launcher/ui/pages/modplatform/DataPackModel.h @@ -21,14 +21,13 @@ class DataPackResourceModel : public ResourceModel { Q_OBJECT public: - DataPackResourceModel(BaseInstance const&, ResourceAPI*); + DataPackResourceModel(BaseInstance const&, ResourceAPI*, QString, QString); /* Ask the API for more information */ void searchWithTerm(const QString& term, unsigned int sort); - void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; - void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; - void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; + [[nodiscard]] QString debugName() const override { return m_debugName; } + [[nodiscard]] QString metaEntryBase() const override { return m_metaEntryBase; } public slots: ResourceAPI::SearchArgs createSearchArguments() override; @@ -38,7 +37,9 @@ class DataPackResourceModel : public ResourceModel { protected: const BaseInstance& m_base_instance; - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; + private: + QString m_debugName; + QString m_metaEntryBase; }; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index feaa4cfa7..c5a03e1fd 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -14,7 +14,9 @@ namespace ResourceDownload { -ModModel::ModModel(BaseInstance& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {} +ModModel::ModModel(BaseInstance& base_inst, ResourceAPI* api, QString debugName, QString metaEntryBase) + : ResourceModel(api), m_base_instance(base_inst), m_debugName(debugName + " (Model)"), m_metaEntryBase(metaEntryBase) +{} /******** Make data requests ********/ @@ -60,7 +62,7 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(const QModelInd if (m_filter->loaders) loaders = m_filter->loaders; - return { pack, versions, loaders }; + return { pack, versions, loaders, ModPlatform::ResourceType::Mod }; } ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(const QModelIndex& entry) diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index bb9255cd0..873d4c1f9 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -24,26 +24,23 @@ class ModModel : public ResourceModel { Q_OBJECT public: - ModModel(BaseInstance&, ResourceAPI* api); + ModModel(BaseInstance&, ResourceAPI* api, QString debugName, QString metaEntryBase); /* Ask the API for more information */ void searchWithTerm(const QString& term, unsigned int sort, bool filter_changed); - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override = 0; - virtual ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) = 0; - void setFilter(std::shared_ptr filter) { m_filter = filter; } virtual QVariant getInstalledPackVersion(ModPlatform::IndexedPack::Ptr) const override; + [[nodiscard]] QString debugName() const override { return m_debugName; } + [[nodiscard]] QString metaEntryBase() const override { return m_metaEntryBase; } + public slots: ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(const QModelIndex&) override; ResourceAPI::ProjectInfoArgs createInfoArguments(const QModelIndex&) override; protected: - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const override; virtual bool checkFilters(ModPlatform::IndexedPack::Ptr) override; @@ -53,6 +50,10 @@ class ModModel : public ResourceModel { BaseInstance& m_base_instance; std::shared_ptr m_filter = nullptr; + + private: + QString m_debugName; + QString m_metaEntryBase; }; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 8e3be5e8f..5ea70789e 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -15,8 +15,8 @@ #include "Application.h" #include "BuildConfig.h" -#include "Json.h" +#include "modplatform/ResourceAPI.h" #include "net/ApiDownload.h" #include "net/NetJob.h" @@ -141,9 +141,9 @@ void ResourceModel::search() if (m_search_term.startsWith("#")) { auto projectId = m_search_term.mid(1); if (!projectId.isEmpty()) { - ResourceAPI::ProjectInfoCallbacks callbacks; + ResourceAPI::Callback callbacks; - callbacks.on_fail = [this](QString reason) { + callbacks.on_fail = [this](QString reason, int) { if (!s_running_models.constFind(this).value()) return; searchRequestFailed(reason, -1); @@ -154,10 +154,10 @@ void ResourceModel::search() searchRequestAborted(); }; - callbacks.on_succeed = [this](auto& doc, auto& pack) { + callbacks.on_succeed = [this](auto& pack) { if (!s_running_models.constFind(this).value()) return; - searchRequestForOneSucceeded(doc); + searchRequestForOneSucceeded(pack); }; if (auto job = m_api->getProjectInfo({ projectId }, std::move(callbacks)); job) runSearchJob(job); @@ -166,27 +166,23 @@ void ResourceModel::search() } auto args{ createSearchArguments() }; - auto callbacks{ createSearchCallbacks() }; + ResourceAPI::Callback> callbacks{}; - // Use defaults if no callbacks are set - if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc) { - if (!s_running_models.constFind(this).value()) - return; - searchRequestSucceeded(doc); - }; - if (!callbacks.on_fail) - callbacks.on_fail = [this](QString reason, int network_error_code) { - if (!s_running_models.constFind(this).value()) - return; - searchRequestFailed(reason, network_error_code); - }; - if (!callbacks.on_abort) - callbacks.on_abort = [this] { - if (!s_running_models.constFind(this).value()) - return; - searchRequestAborted(); - }; + callbacks.on_succeed = [this](auto& doc) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestSucceeded(doc); + }; + callbacks.on_fail = [this](QString reason, int network_error_code) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestFailed(reason, network_error_code); + }; + callbacks.on_abort = [this] { + if (!s_running_models.constFind(this).value()) + return; + searchRequestAborted(); + }; if (auto job = m_api->searchProjects(std::move(args), std::move(callbacks)); job) runSearchJob(job); @@ -201,14 +197,15 @@ void ResourceModel::loadEntry(const QModelIndex& entry) if (!pack->versionsLoaded) { auto args{ createVersionsArguments(entry) }; - auto callbacks{ createVersionsCallbacks(entry) }; + ResourceAPI::Callback> callbacks{}; + auto addonId = pack->addonId; // Use default if no callbacks are set if (!callbacks.on_succeed) - callbacks.on_succeed = [this, entry](auto& doc, auto pack) { + callbacks.on_succeed = [this, entry, addonId](auto& doc) { if (!s_running_models.constFind(this).value()) return; - versionRequestSucceeded(doc, pack, entry); + versionRequestSucceeded(doc, addonId, entry); }; if (!callbacks.on_fail) callbacks.on_fail = [](QString reason, int) { @@ -222,28 +219,23 @@ void ResourceModel::loadEntry(const QModelIndex& entry) if (!pack->extraDataLoaded) { auto args{ createInfoArguments(entry) }; - auto callbacks{ createInfoCallbacks(entry) }; + ResourceAPI::Callback callbacks{}; - // Use default if no callbacks are set - if (!callbacks.on_succeed) - callbacks.on_succeed = [this, entry](auto& doc, auto& newpack) { - if (!s_running_models.constFind(this).value()) - return; - auto pack = newpack; - infoRequestSucceeded(doc, pack, entry); - }; - if (!callbacks.on_fail) - callbacks.on_fail = [this](QString reason) { - if (!s_running_models.constFind(this).value()) - return; - QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load project info: %1").arg(reason)); - }; - if (!callbacks.on_abort) - callbacks.on_abort = [this] { - if (!s_running_models.constFind(this).value()) - return; - qCritical() << tr("The request was aborted for an unknown reason"); - }; + callbacks.on_succeed = [this, entry](auto& newpack) { + if (!s_running_models.constFind(this).value()) + return; + infoRequestSucceeded(newpack, entry); + }; + callbacks.on_fail = [this](QString reason, int) { + if (!s_running_models.constFind(this).value()) + return; + QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load project info: %1").arg(reason)); + }; + callbacks.on_abort = [this] { + if (!s_running_models.constFind(this).value()) + return; + qCritical() << tr("The request was aborted for an unknown reason"); + }; if (auto job = m_api->getProjectInfo(std::move(args), std::move(callbacks)); job) runInfoJob(job); @@ -358,68 +350,35 @@ std::optional ResourceModel::getIcon(QModelIndex& index, const QUrl& url) return {}; } -// No 'forgor to implement' shall pass here :blobfox_knife: -#define NEED_FOR_CALLBACK_ASSERT(name) \ - Q_ASSERT_X(0 != 0, #name, "You NEED to re-implement this if you intend on using the default callbacks.") - -QJsonArray ResourceModel::documentToArray([[maybe_unused]] QJsonDocument& doc) const -{ - NEED_FOR_CALLBACK_ASSERT("documentToArray"); - return {}; -} -void ResourceModel::loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) -{ - NEED_FOR_CALLBACK_ASSERT("loadIndexedPack"); -} -void ResourceModel::loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) -{ - NEED_FOR_CALLBACK_ASSERT("loadExtraPackInfo"); -} -void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) -{ - NEED_FOR_CALLBACK_ASSERT("loadIndexedPackVersions"); -} - /* Default callbacks */ -void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) +void ResourceModel::searchRequestSucceeded(QList& newList) { - QList newList; - auto packs = documentToArray(doc); - - for (auto packRaw : packs) { - auto packObj = packRaw.toObject(); - - ModPlatform::IndexedPack::Ptr pack = std::make_shared(); - try { - loadIndexedPack(*pack, packObj); - if (auto sel = std::find_if(m_selected.begin(), m_selected.end(), - [&pack](const DownloadTaskPtr i) { - const auto ipack = i->getPack(); - return ipack->provider == pack->provider && ipack->addonId == pack->addonId; - }); - sel != m_selected.end()) { - newList.append(sel->get()->getPack()); - } else - newList.append(pack); - } catch (const JSONValidationError& e) { - qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause(); - continue; + QList filteredNewList; + for (auto pack : newList) { + ModPlatform::IndexedPack::Ptr p; + if (auto sel = std::find_if(m_selected.begin(), m_selected.end(), + [&pack](const DownloadTaskPtr i) { + const auto ipack = i->getPack(); + return ipack->provider == pack->provider && ipack->addonId == pack->addonId; + }); + sel != m_selected.end()) { + p = sel->get()->getPack(); + } else { + p = pack; + } + if (checkFilters(p)) { + filteredNewList << p; } } - if (packs.size() < 25) { + if (newList.size() < 25) { m_search_state = SearchState::Finished; } else { m_next_search_offset += 25; m_search_state = SearchState::CanFetchMore; } - QList filteredNewList; - for (auto p : newList) - if (checkFilters(p)) - filteredNewList << p; - // When you have a Qt build with assertions turned on, proceeding here will abort the application if (filteredNewList.size() == 0) return; @@ -429,24 +388,12 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) endInsertRows(); } -void ResourceModel::searchRequestForOneSucceeded(QJsonDocument& doc) +void ResourceModel::searchRequestForOneSucceeded(ModPlatform::IndexedPack& pack) { - ModPlatform::IndexedPack::Ptr pack = std::make_shared(); - - try { - auto obj = Json::requireObject(doc); - if (obj.contains("data")) - obj = Json::requireObject(obj, "data"); - loadIndexedPack(*pack, obj); - } catch (const JSONValidationError& e) { - qDebug() << doc; - qWarning() << "Error while reading " << debugName() << " resource info: " << e.cause(); - } - m_search_state = SearchState::Finished; beginInsertRows(QModelIndex(), m_packs.size(), m_packs.size() + 1); - m_packs.append(pack); + m_packs.append(std::make_shared(pack)); endInsertRows(); } @@ -479,21 +426,16 @@ void ResourceModel::searchRequestAborted() search(); } -void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index) +void ResourceModel::versionRequestSucceeded(QVector& doc, QVariant pack, const QModelIndex& index) { auto current_pack = data(index, Qt::UserRole).value(); // Check if the index is still valid for this resource or not - if (pack.addonId != current_pack->addonId) + if (pack != current_pack->addonId) return; - try { - auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); - loadIndexedPackVersions(*current_pack, arr); - } catch (const JSONValidationError& e) { - qDebug() << doc; - qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause(); - } + current_pack->versions = doc; + current_pack->versionsLoaded = true; // Cache info :^) QVariant new_pack; @@ -506,7 +448,7 @@ void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::Ind emit versionListUpdated(index); } -void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index) +void ResourceModel::infoRequestSucceeded(ModPlatform::IndexedPack& pack, const QModelIndex& index) { auto current_pack = data(index, Qt::UserRole).value(); @@ -514,14 +456,7 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe if (pack.addonId != current_pack->addonId) return; - try { - auto obj = Json::requireObject(doc); - loadExtraPackInfo(*current_pack, obj); - } catch (const JSONValidationError& e) { - qDebug() << doc; - qWarning() << "Error while reading " << debugName() << " resource info: " << e.cause(); - } - + *current_pack = pack; // Cache info :^) QVariant new_pack; new_pack.setValue(current_pack); diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index cae1d6581..0b56b2b6a 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -43,10 +43,7 @@ class ResourceModel : public QAbstractListModel { virtual auto debugName() const -> QString; virtual auto metaEntryBase() const -> QString = 0; - inline int rowCount(const QModelIndex& parent) const override - { - return parent.isValid() ? 0 : static_cast(m_packs.size()); - } + inline int rowCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : static_cast(m_packs.size()); } inline int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : 1; } inline auto flags(const QModelIndex& index) const -> Qt::ItemFlags override { return QAbstractListModel::flags(index); } @@ -77,13 +74,10 @@ class ResourceModel : public QAbstractListModel { void setSearchTerm(QString term) { m_search_term = term; } virtual ResourceAPI::SearchArgs createSearchArguments() = 0; - virtual ResourceAPI::SearchCallbacks createSearchCallbacks() { return {}; } virtual ResourceAPI::VersionSearchArgs createVersionsArguments(const QModelIndex&) = 0; - virtual ResourceAPI::VersionSearchCallbacks createVersionsCallbacks(const QModelIndex&) { return {}; } virtual ResourceAPI::ProjectInfoArgs createInfoArguments(const QModelIndex&) = 0; - virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(const QModelIndex&) { return {}; } /** Requests the API for more entries. */ virtual void search(); @@ -114,22 +108,6 @@ class ResourceModel : public QAbstractListModel { auto getCurrentSortingMethodByIndex() const -> std::optional; - /** Converts a JSON document to a common array format. - * - * This is needed so that different providers, with different JSON structures, can be parsed - * uniformally. You NEED to re-implement this if you intend on using the default callbacks. - */ - virtual auto documentToArray(QJsonDocument&) const -> QJsonArray; - - /** Functions to load data into a pack. - * - * Those are needed for the same reason as documentToArray, and NEED to be re-implemented in the same way. - */ - - virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&); - virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&); - virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&); - virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const { return false; } protected: @@ -159,14 +137,14 @@ class ResourceModel : public QAbstractListModel { private: /* Default search request callbacks */ - void searchRequestSucceeded(QJsonDocument&); - void searchRequestForOneSucceeded(QJsonDocument&); + void searchRequestSucceeded(QList&); + void searchRequestForOneSucceeded(ModPlatform::IndexedPack&); void searchRequestFailed(QString reason, int network_error_code); void searchRequestAborted(); - void versionRequestSucceeded(QJsonDocument&, ModPlatform::IndexedPack&, const QModelIndex&); + void versionRequestSucceeded(QVector&, QVariant, const QModelIndex&); - void infoRequestSucceeded(QJsonDocument&, ModPlatform::IndexedPack&, const QModelIndex&); + void infoRequestSucceeded(ModPlatform::IndexedPack&, const QModelIndex&); signals: void versionListUpdated(const QModelIndex& index); diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.cpp b/launcher/ui/pages/modplatform/ResourcePackModel.cpp index 986cb56a6..e774c6f64 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.cpp +++ b/launcher/ui/pages/modplatform/ResourcePackModel.cpp @@ -8,8 +8,11 @@ namespace ResourceDownload { -ResourcePackResourceModel::ResourcePackResourceModel(BaseInstance const& base_inst, ResourceAPI* api) - : ResourceModel(api), m_base_instance(base_inst) +ResourcePackResourceModel::ResourcePackResourceModel(BaseInstance const& base_inst, + ResourceAPI* api, + QString debugName, + QString metaEntryBase) + : ResourceModel(api), m_base_instance(base_inst), m_debugName(debugName + " (Model)"), m_metaEntryBase(metaEntryBase) {} /******** Make data requests ********/ @@ -23,7 +26,7 @@ ResourceAPI::SearchArgs ResourcePackResourceModel::createSearchArguments() ResourceAPI::VersionSearchArgs ResourcePackResourceModel::createVersionsArguments(const QModelIndex& entry) { auto& pack = m_packs[entry.row()]; - return { *pack }; + return { *pack, {}, {}, ModPlatform::ResourceType::ResourcePack }; } ResourceAPI::ProjectInfoArgs ResourcePackResourceModel::createInfoArguments(const QModelIndex& entry) diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.h b/launcher/ui/pages/modplatform/ResourcePackModel.h index 4f00808e8..d664ccb05 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.h +++ b/launcher/ui/pages/modplatform/ResourcePackModel.h @@ -20,14 +20,13 @@ class ResourcePackResourceModel : public ResourceModel { Q_OBJECT public: - ResourcePackResourceModel(BaseInstance const&, ResourceAPI*); + ResourcePackResourceModel(BaseInstance const&, ResourceAPI*, QString debugName, QString metaEntryBase); /* Ask the API for more information */ void searchWithTerm(const QString& term, unsigned int sort); - void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; - void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; - void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; + [[nodiscard]] QString debugName() const override { return m_debugName; } + [[nodiscard]] QString metaEntryBase() const override { return m_metaEntryBase; } public slots: ResourceAPI::SearchArgs createSearchArguments() override; @@ -37,7 +36,9 @@ class ResourcePackResourceModel : public ResourceModel { protected: const BaseInstance& m_base_instance; - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; + private: + QString m_debugName; + QString m_metaEntryBase; }; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.cpp b/launcher/ui/pages/modplatform/ShaderPackModel.cpp index b59bf182b..f54a868db 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackModel.cpp @@ -8,8 +8,8 @@ namespace ResourceDownload { -ShaderPackResourceModel::ShaderPackResourceModel(BaseInstance const& base_inst, ResourceAPI* api) - : ResourceModel(api), m_base_instance(base_inst) +ShaderPackResourceModel::ShaderPackResourceModel(BaseInstance const& base_inst, ResourceAPI* api, QString debugName, QString metaEntryBase) + : ResourceModel(api), m_base_instance(base_inst), m_debugName(debugName + " (Model)"), m_metaEntryBase(metaEntryBase) {} /******** Make data requests ********/ @@ -23,7 +23,7 @@ ResourceAPI::SearchArgs ShaderPackResourceModel::createSearchArguments() ResourceAPI::VersionSearchArgs ShaderPackResourceModel::createVersionsArguments(const QModelIndex& entry) { auto& pack = m_packs[entry.row()]; - return { *pack }; + return { *pack, {}, {}, ModPlatform::ResourceType::ShaderPack }; } ResourceAPI::ProjectInfoArgs ShaderPackResourceModel::createInfoArguments(const QModelIndex& entry) diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.h b/launcher/ui/pages/modplatform/ShaderPackModel.h index 5bb9e58b1..9856be93e 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.h +++ b/launcher/ui/pages/modplatform/ShaderPackModel.h @@ -20,14 +20,13 @@ class ShaderPackResourceModel : public ResourceModel { Q_OBJECT public: - ShaderPackResourceModel(BaseInstance const&, ResourceAPI*); + ShaderPackResourceModel(BaseInstance const&, ResourceAPI*, QString debugName, QString metaEntryBase); /* Ask the API for more information */ void searchWithTerm(const QString& term, unsigned int sort); - void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; - void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; - void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; + [[nodiscard]] QString debugName() const override { return m_debugName; } + [[nodiscard]] QString metaEntryBase() const override { return m_metaEntryBase; } public slots: ResourceAPI::SearchArgs createSearchArguments() override; @@ -37,7 +36,9 @@ class ShaderPackResourceModel : public ResourceModel { protected: const BaseInstance& m_base_instance; - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; + private: + QString m_debugName; + QString m_metaEntryBase; }; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/TexturePackModel.cpp b/launcher/ui/pages/modplatform/TexturePackModel.cpp index d56f9334b..7c1490671 100644 --- a/launcher/ui/pages/modplatform/TexturePackModel.cpp +++ b/launcher/ui/pages/modplatform/TexturePackModel.cpp @@ -12,8 +12,8 @@ static std::list s_availableVersions = {}; namespace ResourceDownload { -TexturePackResourceModel::TexturePackResourceModel(BaseInstance const& inst, ResourceAPI* api) - : ResourcePackResourceModel(inst, api), m_version_list(APPLICATION->metadataIndex()->get("net.minecraft")) +TexturePackResourceModel::TexturePackResourceModel(BaseInstance const& inst, ResourceAPI* api, QString debugName, QString metaEntryBase) + : ResourcePackResourceModel(inst, api, debugName, metaEntryBase), m_version_list(APPLICATION->metadataIndex()->get("net.minecraft")) { if (!m_version_list->isLoaded()) { qDebug() << "Loading version list..."; @@ -73,6 +73,7 @@ ResourceAPI::SearchArgs TexturePackResourceModel::createSearchArguments() ResourceAPI::VersionSearchArgs TexturePackResourceModel::createVersionsArguments(const QModelIndex& entry) { auto args = ResourcePackResourceModel::createVersionsArguments(entry); + args.resourceType = ModPlatform::ResourceType::TexturePack; if (!m_version_list->isLoaded()) { qCritical() << "The version list could not be loaded. Falling back to showing all entries."; return args; diff --git a/launcher/ui/pages/modplatform/TexturePackModel.h b/launcher/ui/pages/modplatform/TexturePackModel.h index 885bbced8..bb7348b33 100644 --- a/launcher/ui/pages/modplatform/TexturePackModel.h +++ b/launcher/ui/pages/modplatform/TexturePackModel.h @@ -13,7 +13,7 @@ class TexturePackResourceModel : public ResourcePackResourceModel { Q_OBJECT public: - TexturePackResourceModel(BaseInstance const& inst, ResourceAPI* api); + TexturePackResourceModel(BaseInstance const& inst, ResourceAPI* api, QString debugName, QString metaEntryBase); inline ::Version maximumTexturePackVersion() const { return { "1.6" }; } diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index f8fca6570..ea051bd39 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -20,7 +20,7 @@ ListModel::~ListModel() {} int ListModel::rowCount(const QModelIndex& parent) const { - return parent.isValid() ? 0 : modpacks.size(); + return parent.isValid() ? 0 : m_modpacks.size(); } int ListModel::columnCount(const QModelIndex& parent) const @@ -31,27 +31,27 @@ int ListModel::columnCount(const QModelIndex& parent) const QVariant ListModel::data(const QModelIndex& index, int role) const { int pos = index.row(); - if (pos >= modpacks.size() || pos < 0 || !index.isValid()) { + if (pos >= m_modpacks.size() || pos < 0 || !index.isValid()) { return QString("INVALID INDEX %1").arg(pos); } - IndexedPack pack = modpacks.at(pos); + auto pack = m_modpacks.at(pos); switch (role) { case Qt::ToolTipRole: { - if (pack.description.length() > 100) { + if (pack->description.length() > 100) { // some magic to prevent to long tooltips and replace html linebreaks - QString edit = pack.description.left(97); + QString edit = pack->description.left(97); edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); return edit; } - return pack.description; + return pack->description; } case Qt::DecorationRole: { - if (m_logoMap.contains(pack.logoName)) { - return (m_logoMap.value(pack.logoName)); + 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); + ((ListModel*)this)->requestLogo(pack->logoName, pack->logoUrl); return icon; } case Qt::UserRole: { @@ -62,9 +62,9 @@ QVariant ListModel::data(const QModelIndex& index, int role) const case Qt::SizeHintRole: return QSize(0, 58); case UserDataTypes::TITLE: - return pack.name; + return pack->name; case UserDataTypes::DESCRIPTION: - return pack.description; + return pack->description; case UserDataTypes::INSTALLED: return false; default: @@ -76,11 +76,10 @@ QVariant ListModel::data(const QModelIndex& index, int role) const bool ListModel::setData(const QModelIndex& index, const QVariant& value, [[maybe_unused]] int role) { int pos = index.row(); - if (pos >= modpacks.size() || pos < 0 || !index.isValid()) + if (pos >= m_modpacks.size() || pos < 0 || !index.isValid()) return false; - Q_ASSERT(value.canConvert()); - modpacks[pos] = value.value(); + m_modpacks[pos] = value.value(); return true; } @@ -89,8 +88,8 @@ 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) { + for (int i = 0; i < m_modpacks.size(); i++) { + if (m_modpacks[i]->logoName == logo) { emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole }); } } @@ -117,8 +116,8 @@ void ListModel::requestLogo(QString logo, QString url) connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] { job->deleteLater(); emit logoLoaded(logo, QIcon(fullPath)); - if (waitingCallbacks.contains(logo)) { - waitingCallbacks.value(logo)(fullPath); + if (m_waitingCallbacks.contains(logo)) { + m_waitingCallbacks.value(logo)(fullPath); } }); @@ -148,14 +147,14 @@ Qt::ItemFlags ListModel::flags(const QModelIndex& index) const bool ListModel::canFetchMore([[maybe_unused]] const QModelIndex& parent) const { - return searchState == CanPossiblyFetchMore; + return m_searchState == CanPossiblyFetchMore; } void ListModel::fetchMore(const QModelIndex& parent) { if (parent.isValid()) return; - if (nextSearchOffset == 0) { + if (m_nextSearchOffset == 0) { qWarning() << "fetchMore with 0 offset is wrong..."; return; } @@ -164,138 +163,106 @@ void ListModel::fetchMore(const QModelIndex& parent) void ListModel::performPaginatedSearch() { - if (currentSearchTerm.startsWith("#")) { - auto projectId = currentSearchTerm.mid(1); + static const FlameAPI api; + if (m_currentSearchTerm.startsWith("#")) { + auto projectId = m_currentSearchTerm.mid(1); if (!projectId.isEmpty()) { - ResourceAPI::ProjectInfoCallbacks callbacks; + ResourceAPI::Callback callbacks; - callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; - callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; + callbacks.on_fail = [this](QString reason, int) { searchRequestFailed(reason); }; + callbacks.on_succeed = [this](auto& pack) { searchRequestForOneSucceeded(pack); }; callbacks.on_abort = [this] { qCritical() << "Search task aborted by an unknown reason!"; searchRequestFailed("Aborted"); }; - static const FlameAPI api; - if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { - jobPtr = job; - jobPtr->start(); + if (auto job = api.getProjectInfo({ { projectId } }, std::move(callbacks)); job) { + m_jobPtr = job; + m_jobPtr->start(); } return; } } ResourceAPI::SortingMethod sort{}; - sort.index = currentSort + 1; + sort.index = m_currentSort + 1; - auto netJob = makeShared("Flame::Search", APPLICATION->network()); - auto searchUrl = - FlameAPI().getSearchURL({ ModPlatform::ResourceType::Modpack, nextSearchOffset, currentSearchTerm, sort, m_filter->loaders, - m_filter->versions, ModPlatform::Side::NoSide, m_filter->categoryIds, m_filter->openSource }); + ResourceAPI::Callback> callbacks{}; - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl.value()), response)); - jobPtr = netJob; - jobPtr->start(); - connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished); - connect(netJob.get(), &NetJob::failed, this, &ListModel::searchRequestFailed); + callbacks.on_succeed = [this](auto& doc) { searchRequestFinished(doc); }; + callbacks.on_fail = [this](QString reason, int) { searchRequestFailed(reason); }; + + auto netJob = api.searchProjects({ ModPlatform::ResourceType::Modpack, m_nextSearchOffset, m_currentSearchTerm, sort, m_filter->loaders, + m_filter->versions, ModPlatform::Side::NoSide, m_filter->categoryIds, m_filter->openSource }, + std::move(callbacks)); + + m_jobPtr = netJob; + m_jobPtr->start(); } void ListModel::searchWithTerm(const QString& term, int sort, std::shared_ptr filter, bool filterChanged) { - if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort && !filterChanged) { + if (m_currentSearchTerm == term && m_currentSearchTerm.isNull() == term.isNull() && m_currentSort == sort && !filterChanged) { return; } - currentSearchTerm = term; - currentSort = sort; + m_currentSearchTerm = term; + m_currentSort = sort; m_filter = filter; if (hasActiveSearchJob()) { - jobPtr->abort(); - searchState = ResetRequested; + m_jobPtr->abort(); + m_searchState = ResetRequested; return; } beginResetModel(); - modpacks.clear(); + m_modpacks.clear(); endResetModel(); - searchState = None; + m_searchState = None; - nextSearchOffset = 0; + m_nextSearchOffset = 0; performPaginatedSearch(); } -void Flame::ListModel::searchRequestFinished() +void Flame::ListModel::searchRequestFinished(QList& newList) { if (hasActiveSearchJob()) return; - 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 = Json::ensureArray(doc.object(), "data"); - 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; + if (newList.size() < 25) { + m_searchState = Finished; } else { - nextSearchOffset += 25; - searchState = CanPossiblyFetchMore; + m_nextSearchOffset += 25; + m_searchState = CanPossiblyFetchMore; } // When you have a Qt build with assertions turned on, proceeding here will abort the application if (newList.size() == 0) return; - beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + newList.size() - 1); - modpacks.append(newList); + beginInsertRows(QModelIndex(), m_modpacks.size(), m_modpacks.size() + newList.size() - 1); + m_modpacks.append(newList); endInsertRows(); } -void Flame::ListModel::searchRequestForOneSucceeded(QJsonDocument& doc) +void Flame::ListModel::searchRequestForOneSucceeded(ModPlatform::IndexedPack& pack) { - jobPtr.reset(); + m_jobPtr.reset(); - auto packObj = Json::ensureObject(doc.object(), "data"); - - Flame::IndexedPack pack; - try { - Flame::loadIndexedPack(pack, packObj); - } catch (const JSONValidationError& e) { - qWarning() << "Error while loading pack from CurseForge: " << e.cause(); - return; - } - - beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + 1); - modpacks.append({ pack }); + beginInsertRows(QModelIndex(), m_modpacks.size(), m_modpacks.size() + 1); + m_modpacks.append(std::make_shared(pack)); endInsertRows(); } void Flame::ListModel::searchRequestFailed(QString reason) { - jobPtr.reset(); + m_jobPtr.reset(); - if (searchState == ResetRequested) { + if (m_searchState == ResetRequested) { beginResetModel(); - modpacks.clear(); + m_modpacks.clear(); endResetModel(); - nextSearchOffset = 0; + m_nextSearchOffset = 0; performPaginatedSearch(); } else { - searchState = Finished; + m_searchState = Finished; } } diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.h b/launcher/ui/pages/modplatform/flame/FlameModel.h index bfdd81810..f98e2be96 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.h +++ b/launcher/ui/pages/modplatform/flame/FlameModel.h @@ -16,8 +16,6 @@ #include #include "ui/widgets/ModFilterWidget.h" -#include - namespace Flame { using LogoMap = QMap; @@ -41,8 +39,8 @@ class ListModel : public QAbstractListModel { void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); void searchWithTerm(const QString& term, int sort, std::shared_ptr filter, bool filterChanged); - bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } - Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } + bool hasActiveSearchJob() const { return m_jobPtr && m_jobPtr->isRunning(); } + Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? m_jobPtr : nullptr; } private slots: void performPaginatedSearch(); @@ -50,27 +48,26 @@ class ListModel : public QAbstractListModel { void logoFailed(QString logo); void logoLoaded(QString logo, QIcon out); - void searchRequestFinished(); + void searchRequestFinished(QList&); void searchRequestFailed(QString reason); - void searchRequestForOneSucceeded(QJsonDocument&); + void searchRequestForOneSucceeded(ModPlatform::IndexedPack&); private: void requestLogo(QString file, QString url); private: - QList modpacks; + QList m_modpacks; QStringList m_failedLogos; QStringList m_loadingLogos; LogoMap m_logoMap; - QMap waitingCallbacks; + QMap m_waitingCallbacks; - QString currentSearchTerm; - int currentSort = 0; + QString m_currentSearchTerm; + int m_currentSort = 0; std::shared_ptr m_filter; - int nextSearchOffset = 0; - enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None; - Task::Ptr jobPtr; - std::shared_ptr response = std::make_shared(); + int m_nextSearchOffset = 0; + enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } m_searchState = None; + Task::Ptr m_jobPtr; }; } // namespace Flame diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 5bc314cc2..059d65438 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -35,7 +35,8 @@ #include "FlamePage.h" #include "Version.h" -#include "modplatform/flame/FlamePackIndex.h" +#include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/widgets/ModFilterWidget.h" #include "ui_FlamePage.h" @@ -43,29 +44,25 @@ #include #include -#include "Application.h" #include "FlameModel.h" #include "InstanceImportTask.h" -#include "Json.h" #include "StringUtils.h" #include "modplatform/flame/FlameAPI.h" #include "ui/dialogs/NewInstanceDialog.h" #include "ui/widgets/ProjectItem.h" -#include "net/ApiDownload.h" - static FlameAPI api; FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) - : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog), m_fetch_progress(this, false) + : QWidget(parent), m_ui(new Ui::FlamePage), m_dialog(dialog), m_fetch_progress(this, false) { - ui->setupUi(this); - ui->searchEdit->installEventFilter(this); - listModel = new Flame::ListModel(this); - ui->packView->setModel(listModel); + m_ui->setupUi(this); + m_ui->searchEdit->installEventFilter(this); + m_listModel = new Flame::ListModel(this); + m_ui->packView->setModel(m_listModel); - ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + m_ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); m_search_timer.setTimerType(Qt::TimerType::CoarseTimer); m_search_timer.setSingleShot(true); @@ -76,33 +73,33 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) m_fetch_progress.setFixedHeight(24); m_fetch_progress.progressFormat(""); - ui->verticalLayout->insertWidget(2, &m_fetch_progress); + m_ui->verticalLayout->insertWidget(2, &m_fetch_progress); // 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")); + m_ui->sortByBox->addItem(tr("Sort by Featured")); + m_ui->sortByBox->addItem(tr("Sort by Popularity")); + m_ui->sortByBox->addItem(tr("Sort by Last Updated")); + m_ui->sortByBox->addItem(tr("Sort by Name")); + m_ui->sortByBox->addItem(tr("Sort by Author")); + m_ui->sortByBox->addItem(tr("Sort by Total Downloads")); - connect(ui->sortByBox, &QComboBox::currentIndexChanged, this, &FlamePage::triggerSearch); - connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlamePage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlamePage::onVersionSelectionChanged); + connect(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &FlamePage::triggerSearch); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlamePage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlamePage::onVersionSelectionChanged); - ui->packView->setItemDelegate(new ProjectItemDelegate(this)); - ui->packDescription->setMetaEntry("FlamePacks"); + m_ui->packView->setItemDelegate(new ProjectItemDelegate(this)); + m_ui->packDescription->setMetaEntry("FlamePacks"); createFilterWidget(); } FlamePage::~FlamePage() { - delete ui; + delete m_ui; } bool FlamePage::eventFilter(QObject* watched, QEvent* event) { - if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) { + if (watched == m_ui->searchEdit && event->type() == QEvent::KeyPress) { QKeyEvent* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Return) { triggerSearch(); @@ -125,7 +122,7 @@ bool FlamePage::shouldDisplay() const void FlamePage::retranslate() { - ui->retranslateUi(this); + m_ui->retranslateUi(this); } void FlamePage::openedImpl() @@ -136,109 +133,91 @@ void FlamePage::openedImpl() void FlamePage::triggerSearch() { - ui->packView->selectionModel()->setCurrentIndex({}, QItemSelectionModel::SelectionFlag::ClearAndSelect); - ui->packView->clearSelection(); - ui->packDescription->clear(); - ui->versionSelectionBox->clear(); + m_ui->packView->selectionModel()->setCurrentIndex({}, QItemSelectionModel::SelectionFlag::ClearAndSelect); + m_ui->packView->clearSelection(); + m_ui->packDescription->clear(); + m_ui->versionSelectionBox->clear(); bool filterChanged = m_filterWidget->changed(); - listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), m_filterWidget->getFilter(), filterChanged); - m_fetch_progress.watch(listModel->activeSearchJob().get()); -} - -bool checkVersionFilters(const Flame::IndexedVersion& v, std::shared_ptr filter) -{ - if (!filter) - return true; - return ((!filter->loaders || !v.loaders || filter->loaders & v.loaders) && // loaders - (filter->releases.empty() || // releases - std::find(filter->releases.cbegin(), filter->releases.cend(), v.version_type) != filter->releases.cend()) && - filter->checkMcVersions({ v.mcVersion })); // mcVersions} + m_listModel->searchWithTerm(m_ui->searchEdit->text(), m_ui->sortByBox->currentIndex(), m_filterWidget->getFilter(), filterChanged); + m_fetch_progress.watch(m_listModel->activeSearchJob().get()); } void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev) { - ui->versionSelectionBox->clear(); + m_ui->versionSelectionBox->clear(); if (!curr.isValid()) { if (isOpened) { - dialog->setSuggestedPack(); + m_dialog->setSuggestedPack(); } return; } - QVariant raw = listModel->data(curr, Qt::UserRole); - Q_ASSERT(raw.canConvert()); - current = raw.value(); + m_current = m_listModel->data(curr, Qt::UserRole).value(); - if (!current.versionsLoaded || m_filterWidget->changed()) { + if (!m_current->versionsLoaded || m_filterWidget->changed()) { qDebug() << "Loading flame modpack versions"; - auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network()); - auto response = std::make_shared(); - int addonId = current.addonId; - netJob->addNetAction( - Net::ApiDownload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files").arg(addonId), response)); - connect(netJob, &NetJob::succeeded, this, [this, response, addonId, curr] { - if (addonId != current.addonId) { + ResourceAPI::Callback > callbacks{}; + + auto addonId = m_current->addonId; + // Use default if no callbacks are set + callbacks.on_succeed = [this, curr, addonId](auto& doc) { + if (addonId != m_current->addonId) { return; // wrong request } - 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; - } - auto arr = Json::ensureArray(doc.object(), "data"); - try { - Flame::loadIndexedPackVersions(current, arr); - } catch (const JSONValidationError& e) { - qDebug() << *response; - qWarning() << "Error while reading flame modpack version: " << e.cause(); - } - auto pred = [this](const Flame::IndexedVersion& v) { return !checkVersionFilters(v, m_filterWidget->getFilter()); }; + m_current->versions = doc; + m_current->versionsLoaded = true; + auto pred = [this](const ModPlatform::IndexedVersion& v) { + if (auto filter = m_filterWidget->getFilter()) + return !filter->checkModpackFilters(v); + return false; + }; #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) - current.versions.removeIf(pred); + m_current->versions.removeIf(pred); #else - for (auto it = current.versions.begin(); it != current.versions.end();) - if (pred(*it)) - it = current.versions.erase(it); - else - ++it; + for (auto it = m_current->versions.begin(); it != m_current->versions.end();) + if (pred(*it)) + it = m_current->versions.erase(it); + else + ++it; #endif - for (const auto& version : current.versions) { - ui->versionSelectionBox->addItem(Flame::getVersionDisplayString(version), QVariant(version.downloadUrl)); + for (auto version : m_current->versions) { + m_ui->versionSelectionBox->addItem(version.getVersionDisplayString(), QVariant(version.downloadUrl)); } QVariant current_updated; - current_updated.setValue(current); + current_updated.setValue(m_current); - if (!listModel->setData(curr, current_updated, Qt::UserRole)) + if (!m_listModel->setData(curr, current_updated, Qt::UserRole)) qWarning() << "Failed to cache versions for the current pack!"; // TODO: Check whether it's a connection issue or the project disabled 3rd-party distribution. - if (current.versionsLoaded && ui->versionSelectionBox->count() < 1) { - ui->versionSelectionBox->addItem(tr("No version is available!"), -1); + if (m_current->versionsLoaded && m_ui->versionSelectionBox->count() < 1) { + m_ui->versionSelectionBox->addItem(tr("No version is available!"), -1); } suggestCurrent(); - }); - connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); }); - connect(netJob, &NetJob::failed, - [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); + }; + callbacks.on_fail = [this](QString reason, int) { + CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); + }; + + auto netJob = api.getProjectVersions({ *m_current, {}, {}, ModPlatform::ResourceType::Modpack }, std::move(callbacks)); + + m_job = netJob; netJob->start(); } else { - for (auto version : current.versions) { - ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl)); + for (auto version : m_current->versions) { + m_ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl)); } suggestCurrent(); } // TODO: Check whether it's a connection issue or the project disabled 3rd-party distribution. - if (current.versionsLoaded && ui->versionSelectionBox->count() < 1) { - ui->versionSelectionBox->addItem(tr("No version is available!"), -1); + if (m_current->versionsLoaded && m_ui->versionSelectionBox->count() < 1) { + m_ui->versionSelectionBox->addItem(tr("No version is available!"), -1); } updateUi(); @@ -251,26 +230,26 @@ void FlamePage::suggestCurrent() } if (m_selected_version_index == -1) { - dialog->setSuggestedPack(); + m_dialog->setSuggestedPack(); return; } - auto version = current.versions.at(m_selected_version_index); + auto version = m_current->versions.at(m_selected_version_index); QMap extra_info; - extra_info.insert("pack_id", QString::number(current.addonId)); - extra_info.insert("pack_version_id", QString::number(version.fileId)); + extra_info.insert("pack_id", m_current->addonId.toString()); + extra_info.insert("pack_version_id", version.fileId.toString()); - dialog->setSuggestedPack(current.name, new InstanceImportTask(version.downloadUrl, this, std::move(extra_info))); - QString editedLogoName = "curseforge_" + current.logoName; - listModel->getLogo(current.logoName, current.logoUrl, - [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); + m_dialog->setSuggestedPack(m_current->name, new InstanceImportTask(version.downloadUrl, this, std::move(extra_info))); + QString editedLogoName = "curseforge_" + m_current->logoName; + m_listModel->getLogo(m_current->logoName, m_current->logoUrl, + [this, editedLogoName](QString logo) { m_dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } void FlamePage::onVersionSelectionChanged(int index) { bool is_blocked = false; - ui->versionSelectionBox->itemData(index).toInt(&is_blocked); + m_ui->versionSelectionBox->itemData(index).toInt(&is_blocked); if (index == -1 || is_blocked) { m_selected_version_index = -1; @@ -279,7 +258,7 @@ void FlamePage::onVersionSelectionChanged(int index) m_selected_version_index = index; - Q_ASSERT(current.versions.at(m_selected_version_index).downloadUrl == ui->versionSelectionBox->currentData().toString()); + Q_ASSERT(m_current->versions.at(m_selected_version_index).downloadUrl == m_ui->versionSelectionBox->currentData().toString()); suggestCurrent(); } @@ -287,66 +266,67 @@ void FlamePage::onVersionSelectionChanged(int index) void FlamePage::updateUi() { QString text = ""; - QString name = current.name; + QString name = m_current->name; - if (current.extra.websiteUrl.isEmpty()) + if (m_current->websiteUrl.isEmpty()) text = name; else - text = "" + name + ""; - if (!current.authors.empty()) { - auto authorToStr = [](Flame::ModpackAuthor& author) { + text = "websiteUrl + "\">" + name + ""; + if (!m_current->authors.empty()) { + auto authorToStr = [](ModPlatform::ModpackAuthor& author) { if (author.url.isEmpty()) { return author.name; } return QString("%2").arg(author.url, author.name); }; QStringList authorStrs; - for (auto& author : current.authors) { + for (auto& author : m_current->authors) { authorStrs.push_back(authorToStr(author)); } text += "
" + tr(" by ") + authorStrs.join(", "); } - if (current.extraInfoLoaded) { - if (!current.extra.issuesUrl.isEmpty() || !current.extra.sourceUrl.isEmpty() || !current.extra.wikiUrl.isEmpty()) { + if (m_current->extraDataLoaded) { + if (!m_current->extraData.issuesUrl.isEmpty() || !m_current->extraData.sourceUrl.isEmpty() || + !m_current->extraData.wikiUrl.isEmpty()) { text += "

" + tr("External links:") + "
"; } - if (!current.extra.issuesUrl.isEmpty()) - text += "- " + tr("Issues: %1").arg(current.extra.issuesUrl) + "
"; - if (!current.extra.wikiUrl.isEmpty()) - text += "- " + tr("Wiki: %1").arg(current.extra.wikiUrl) + "
"; - if (!current.extra.sourceUrl.isEmpty()) - text += "- " + tr("Source code: %1").arg(current.extra.sourceUrl) + "
"; + if (!m_current->extraData.issuesUrl.isEmpty()) + text += "- " + tr("Issues: %1").arg(m_current->extraData.issuesUrl) + "
"; + if (!m_current->extraData.wikiUrl.isEmpty()) + text += "- " + tr("Wiki: %1").arg(m_current->extraData.wikiUrl) + "
"; + if (!m_current->extraData.sourceUrl.isEmpty()) + text += "- " + tr("Source code: %1").arg(m_current->extraData.sourceUrl) + "
"; } text += "
"; - text += api.getModDescription(current.addonId).toUtf8(); + text += api.getModDescription(m_current->addonId.toInt()).toUtf8(); - ui->packDescription->setHtml(StringUtils::htmlListPatch(text + current.description)); - ui->packDescription->flush(); + m_ui->packDescription->setHtml(StringUtils::htmlListPatch(text + m_current->description)); + m_ui->packDescription->flush(); } QString FlamePage::getSerachTerm() const { - return ui->searchEdit->text(); + return m_ui->searchEdit->text(); } void FlamePage::setSearchTerm(QString term) { - ui->searchEdit->setText(term); + m_ui->searchEdit->setText(term); } void FlamePage::createFilterWidget() { auto widget = ModFilterWidget::create(nullptr, false); m_filterWidget.swap(widget); - auto old = ui->splitter->replaceWidget(0, m_filterWidget.get()); + auto old = m_ui->splitter->replaceWidget(0, m_filterWidget.get()); // because we replaced the widget we also need to delete it if (old) { delete old; } - connect(ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); }); + connect(m_ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); }); connect(m_filterWidget.get(), &ModFilterWidget::filterChanged, this, &FlamePage::triggerSearch); auto response = std::make_shared(); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index 19c8d4dbc..2252efa07 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -38,8 +38,8 @@ #include #include -#include #include +#include "modplatform/ModIndex.h" #include "ui/pages/modplatform/ModpackProviderBasePage.h" #include "ui/widgets/ModFilterWidget.h" #include "ui/widgets/ProgressWidget.h" @@ -88,10 +88,10 @@ class FlamePage : public QWidget, public ModpackProviderBasePage { void createFilterWidget(); private: - Ui::FlamePage* ui = nullptr; - NewInstanceDialog* dialog = nullptr; - Flame::ListModel* listModel = nullptr; - Flame::IndexedPack current; + Ui::FlamePage* m_ui = nullptr; + NewInstanceDialog* m_dialog = nullptr; + Flame::ListModel* m_listModel = nullptr; + ModPlatform::IndexedPack::Ptr m_current; int m_selected_version_index = -1; @@ -102,4 +102,5 @@ class FlamePage : public QWidget, public ModpackProviderBasePage { std::unique_ptr m_filterWidget; Task::Ptr m_categoriesTask; + Task::Ptr m_job; }; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index 9917c29e6..a40e6d5a3 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -8,7 +8,7 @@ #include "minecraft/PackProfile.h" #include "modplatform/flame/FlameAPI.h" -#include "modplatform/flame/FlameModIndex.h" +#include "ui/pages/modplatform/flame/FlameResourcePages.h" namespace ResourceDownload { @@ -17,97 +17,9 @@ static bool isOptedOut(const ModPlatform::IndexedVersion& ver) return ver.downloadUrl.isEmpty(); } -FlameModModel::FlameModModel(BaseInstance& base) : ModModel(base, new FlameAPI) {} - -void FlameModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadIndexedPack(m, obj); -} - -// We already deal with the URLs when initializing the pack, due to the API response's structure -void FlameModModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadBody(m, obj); -} - -void FlameModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - FlameMod::loadIndexedPackVersions(m, arr); -} - -auto FlameModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion -{ - return FlameMod::loadDependencyVersions(m, arr, &m_base_instance); -} - -bool FlameModModel::optedOut(const ModPlatform::IndexedVersion& ver) const -{ - return isOptedOut(ver); -} - -auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return Json::ensureArray(obj.object(), "data"); -} - -FlameResourcePackModel::FlameResourcePackModel(const BaseInstance& base) : ResourcePackResourceModel(base, new FlameAPI) {} - -void FlameResourcePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadIndexedPack(m, obj); -} - -// We already deal with the URLs when initializing the pack, due to the API response's structure -void FlameResourcePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadBody(m, obj); -} - -void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - FlameMod::loadIndexedPackVersions(m, arr); -} - -bool FlameResourcePackModel::optedOut(const ModPlatform::IndexedVersion& ver) const -{ - return isOptedOut(ver); -} - -auto FlameResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return Json::ensureArray(obj.object(), "data"); -} - -FlameTexturePackModel::FlameTexturePackModel(const BaseInstance& base) : TexturePackResourceModel(base, new FlameAPI) {} - -void FlameTexturePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadIndexedPack(m, obj); -} - -// We already deal with the URLs when initializing the pack, due to the API response's structure -void FlameTexturePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadBody(m, obj); -} - -void FlameTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - FlameMod::loadIndexedPackVersions(m, arr); - - QList filtered_versions(m.versions.size()); - - // FIXME: Client-side version filtering. This won't take into account any user-selected filtering. - for (auto const& version : m.versions) { - auto const& mc_versions = version.mcVersion; - - if (std::any_of(mc_versions.constBegin(), mc_versions.constEnd(), - [this](auto const& mc_version) { return Version(mc_version) <= maximumTexturePackVersion(); })) - filtered_versions.push_back(version); - } - - m.versions = filtered_versions; -} +FlameTexturePackModel::FlameTexturePackModel(const BaseInstance& base) + : TexturePackResourceModel(base, new FlameAPI, Flame::debugName(), Flame::metaEntryBase()) +{} ResourceAPI::SearchArgs FlameTexturePackModel::createSearchArguments() { @@ -137,65 +49,4 @@ bool FlameTexturePackModel::optedOut(const ModPlatform::IndexedVersion& ver) con return isOptedOut(ver); } -auto FlameTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return Json::ensureArray(obj.object(), "data"); -} - -FlameShaderPackModel::FlameShaderPackModel(const BaseInstance& base) : ShaderPackResourceModel(base, new FlameAPI) {} - -void FlameShaderPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadIndexedPack(m, obj); -} - -// We already deal with the URLs when initializing the pack, due to the API response's structure -void FlameShaderPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadBody(m, obj); -} - -void FlameShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - FlameMod::loadIndexedPackVersions(m, arr); -} - -bool FlameShaderPackModel::optedOut(const ModPlatform::IndexedVersion& ver) const -{ - return isOptedOut(ver); -} - -auto FlameShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return Json::ensureArray(obj.object(), "data"); -} - -FlameDataPackModel::FlameDataPackModel(const BaseInstance& base) : DataPackResourceModel(base, new FlameAPI) {} - -void FlameDataPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadIndexedPack(m, obj); -} - -// We already deal with the URLs when initializing the pack, due to the API response's structure -void FlameDataPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - FlameMod::loadBody(m, obj); -} - -void FlameDataPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - FlameMod::loadIndexedPackVersions(m, arr); -} - -bool FlameDataPackModel::optedOut(const ModPlatform::IndexedVersion& ver) const -{ - return isOptedOut(ver); -} - -auto FlameDataPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return Json::ensureArray(obj.object(), "data"); -} - } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 2cdc2910d..76062f8e6 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -5,52 +5,10 @@ #pragma once #include "ui/pages/modplatform/ModModel.h" -#include "ui/pages/modplatform/ResourcePackModel.h" #include "ui/pages/modplatform/flame/FlameResourcePages.h" namespace ResourceDownload { -class FlameModModel : public ModModel { - Q_OBJECT - - public: - FlameModModel(BaseInstance&); - ~FlameModModel() override = default; - - bool optedOut(const ModPlatform::IndexedVersion& ver) const override; - - private: - QString debugName() const override { return Flame::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Flame::metaEntryBase(); } - - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; - - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; -}; - -class FlameResourcePackModel : public ResourcePackResourceModel { - Q_OBJECT - - public: - FlameResourcePackModel(const BaseInstance&); - ~FlameResourcePackModel() override = default; - - bool optedOut(const ModPlatform::IndexedVersion& ver) const override; - - private: - QString debugName() const override { return Flame::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Flame::metaEntryBase(); } - - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; -}; - class FlameTexturePackModel : public TexturePackResourceModel { Q_OBJECT @@ -64,52 +22,8 @@ class FlameTexturePackModel : public TexturePackResourceModel { QString debugName() const override { return Flame::debugName() + " (Model)"; } QString metaEntryBase() const override { return Flame::metaEntryBase(); } - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(const QModelIndex&) override; - - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; -}; - -class FlameShaderPackModel : public ShaderPackResourceModel { - Q_OBJECT - - public: - FlameShaderPackModel(const BaseInstance&); - ~FlameShaderPackModel() override = default; - - bool optedOut(const ModPlatform::IndexedVersion& ver) const override; - - private: - QString debugName() const override { return Flame::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Flame::metaEntryBase(); } - - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; -}; - -class FlameDataPackModel : public DataPackResourceModel { - Q_OBJECT - - public: - FlameDataPackModel(const BaseInstance&); - ~FlameDataPackModel() override = default; - - bool optedOut(const ModPlatform::IndexedVersion& ver) const override; - - private: - QString debugName() const override { return Flame::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Flame::metaEntryBase(); } - - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index bf421c036..6ff435854 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -40,7 +40,6 @@ #include "FlameResourcePages.h" #include #include -#include "modplatform/ModIndex.h" #include "modplatform/flame/FlameAPI.h" #include "ui_ResourcePage.h" @@ -51,7 +50,7 @@ namespace ResourceDownload { FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ModPage(dialog, instance) { - m_model = new FlameModModel(instance); + m_model = new ModModel(instance, new FlameAPI(), Flame::debugName(), Flame::metaEntryBase()); m_ui->packView->setModel(m_model); addSortings(); @@ -85,7 +84,7 @@ void FlameModPage::openUrl(const QUrl& url) FlameResourcePackPage::FlameResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) : ResourcePackResourcePage(dialog, instance) { - m_model = new FlameResourcePackModel(instance); + m_model = new ResourcePackResourceModel(instance, new FlameAPI(), Flame::debugName(), Flame::metaEntryBase()); m_ui->packView->setModel(m_model); addSortings(); @@ -169,7 +168,7 @@ void FlameDataPackPage::openUrl(const QUrl& url) FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) : ShaderPackResourcePage(dialog, instance) { - m_model = new FlameShaderPackModel(instance); + m_model = new ShaderPackResourceModel(instance, new FlameAPI(), Flame::debugName(), Flame::metaEntryBase()); m_ui->packView->setModel(m_model); addSortings(); @@ -184,10 +183,9 @@ FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseI m_ui->packDescription->setMetaEntry(metaEntryBase()); } -FlameDataPackPage::FlameDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance) - : DataPackResourcePage(dialog, instance) +FlameDataPackPage::FlameDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance) : DataPackResourcePage(dialog, instance) { - m_model = new FlameDataPackModel(instance); + m_model = new DataPackResourceModel(instance, new FlameAPI(), Flame::debugName(), Flame::metaEntryBase()); m_ui->packView->setModel(m_model); addSortings(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 514b33574..bf6215356 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -62,7 +62,7 @@ void ModpackListModel::fetchMore(const QModelIndex& parent) { if (parent.isValid()) return; - if (nextSearchOffset == 0) { + if (m_nextSearchOffset == 0) { qWarning() << "fetchMore with 0 offset is wrong..."; return; } @@ -72,27 +72,27 @@ void ModpackListModel::fetchMore(const QModelIndex& parent) auto ModpackListModel::data(const QModelIndex& index, int role) const -> QVariant { int pos = index.row(); - if (pos >= modpacks.size() || pos < 0 || !index.isValid()) { + if (pos >= m_modpacks.size() || pos < 0 || !index.isValid()) { return QString("INVALID INDEX %1").arg(pos); } - Modrinth::Modpack pack = modpacks.at(pos); + auto pack = m_modpacks.at(pos); switch (role) { case Qt::ToolTipRole: { - if (pack.description.length() > 100) { + if (pack->description.length() > 100) { // some magic to prevent to long tooltips and replace html linebreaks - QString edit = pack.description.left(97); + QString edit = pack->description.left(97); edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); return edit; } - return pack.description; + return pack->description; } case Qt::DecorationRole: { - if (m_logoMap.contains(pack.iconName)) - return m_logoMap.value(pack.iconName); + if (m_logoMap.contains(pack->logoName)) + return m_logoMap.value(pack->logoName); QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); - ((ModpackListModel*)this)->requestLogo(pack.iconName, pack.iconUrl.toString()); + ((ModpackListModel*)this)->requestLogo(pack->logoName, pack->logoUrl); return icon; } case Qt::UserRole: { @@ -104,9 +104,9 @@ auto ModpackListModel::data(const QModelIndex& index, int role) const -> QVarian return QSize(0, 58); // Custom data case UserDataTypes::TITLE: - return pack.name; + return pack->name; case UserDataTypes::DESCRIPTION: - return pack.description; + return pack->description; case UserDataTypes::INSTALLED: return false; default: @@ -119,11 +119,10 @@ auto ModpackListModel::data(const QModelIndex& index, int role) const -> QVarian bool ModpackListModel::setData(const QModelIndex& index, const QVariant& value, [[maybe_unused]] int role) { int pos = index.row(); - if (pos >= modpacks.size() || pos < 0 || !index.isValid()) + if (pos >= m_modpacks.size() || pos < 0 || !index.isValid()) return false; - Q_ASSERT(value.canConvert()); - modpacks[pos] = value.value(); + m_modpacks[pos] = value.value(); return true; } @@ -132,68 +131,56 @@ void ModpackListModel::performPaginatedSearch() { if (hasActiveSearchJob()) return; + static const ModrinthAPI api; - if (currentSearchTerm.startsWith("#")) { - auto projectId = currentSearchTerm.mid(1); + if (m_currentSearchTerm.startsWith("#")) { + auto projectId = m_currentSearchTerm.mid(1); if (!projectId.isEmpty()) { - ResourceAPI::ProjectInfoCallbacks callbacks; + ResourceAPI::Callback callbacks; - callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; - callbacks.on_succeed = [this](auto& doc, auto&) { searchRequestForOneSucceeded(doc); }; + callbacks.on_fail = [this](QString reason, int) { searchRequestFailed(reason); }; + callbacks.on_succeed = [this](auto& pack) { searchRequestForOneSucceeded(pack); }; callbacks.on_abort = [this] { qCritical() << "Search task aborted by an unknown reason!"; searchRequestFailed("Aborted"); }; - static const ModrinthAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { - jobPtr = job; - jobPtr->start(); + m_jobPtr = job; + m_jobPtr->start(); } return; } } // TODO: Move to standalone API ResourceAPI::SortingMethod sort{}; - sort.name = currentSort; - auto searchUrl = - ModrinthAPI().getSearchURL({ ModPlatform::ResourceType::Modpack, nextSearchOffset, currentSearchTerm, sort, m_filter->loaders, - m_filter->versions, ModPlatform::Side::NoSide, m_filter->categoryIds, m_filter->openSource }); + sort.name = m_currentSort; - auto netJob = makeShared("Modrinth::SearchModpack", APPLICATION->network()); - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl.value()), m_allResponse)); + ResourceAPI::Callback> callbacks{}; - connect(netJob.get(), &NetJob::succeeded, this, [this] { - QJsonParseError parseError{}; + callbacks.on_succeed = [this](auto& doc) { searchRequestFinished(doc); }; + callbacks.on_fail = [this](QString reason, int) { searchRequestFailed(reason); }; - QJsonDocument doc = QJsonDocument::fromJson(*m_allResponse, &parseError); - if (parseError.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from " << debugName() << " at " << parseError.offset - << " reason: " << parseError.errorString(); - qWarning() << *m_allResponse; - return; - } + auto netJob = api.searchProjects({ ModPlatform::ResourceType::Modpack, m_nextSearchOffset, m_currentSearchTerm, sort, m_filter->loaders, + m_filter->versions, ModPlatform::Side::NoSide, m_filter->categoryIds, m_filter->openSource }, + std::move(callbacks)); - searchRequestFinished(doc); - }); - connect(netJob.get(), &NetJob::failed, this, &ModpackListModel::searchRequestFailed); - - jobPtr = netJob; - jobPtr->start(); + m_jobPtr = netJob; + m_jobPtr->start(); } void ModpackListModel::refresh() { if (hasActiveSearchJob()) { - jobPtr->abort(); - searchState = ResetRequested; + m_jobPtr->abort(); + m_searchState = ResetRequested; return; } beginResetModel(); - modpacks.clear(); + m_modpacks.clear(); endResetModel(); - searchState = None; + m_searchState = None; - nextSearchOffset = 0; + m_nextSearchOffset = 0; performPaginatedSearch(); } @@ -224,12 +211,12 @@ void ModpackListModel::searchWithTerm(const QString& term, auto sort_str = sortFromIndex(sort); - if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort_str && !filterChanged) { + if (m_currentSearchTerm == term && m_currentSearchTerm.isNull() == term.isNull() && m_currentSort == sort_str && !filterChanged) { return; } - currentSearchTerm = term; - currentSort = sort_str; + m_currentSearchTerm = term; + m_currentSort = sort_str; m_filter = filter; refresh(); @@ -259,8 +246,8 @@ void ModpackListModel::requestLogo(QString logo, QString url) connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] { job->deleteLater(); emit logoLoaded(logo, QIcon(fullPath)); - if (waitingCallbacks.contains(logo)) { - waitingCallbacks.value(logo)(fullPath); + if (m_waitingCallbacks.contains(logo)) { + m_waitingCallbacks.value(logo)(fullPath); } }); @@ -279,8 +266,8 @@ void ModpackListModel::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].iconName == logo) { + for (int i = 0; i < m_modpacks.size(); i++) { + if (m_modpacks[i]->logoName == logo) { emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole }); } } @@ -292,65 +279,38 @@ void ModpackListModel::logoFailed(QString logo) m_loadingLogos.removeAll(logo); } -void ModpackListModel::searchRequestFinished(QJsonDocument& doc_all) +void ModpackListModel::searchRequestFinished(QList& newList) { - jobPtr.reset(); + m_jobPtr.reset(); - QList newList; - - auto packs_all = doc_all.object().value("hits").toArray(); - for (auto packRaw : packs_all) { - auto packObj = packRaw.toObject(); - - Modrinth::Modpack pack; - try { - Modrinth::loadIndexedPack(pack, packObj); - newList.append(pack); - } catch (const JSONValidationError& e) { - qWarning() << "Error while loading mod from " << m_parent->debugName() << ": " << e.cause(); - continue; - } - } - - if (packs_all.size() < m_modpacks_per_page) { - searchState = Finished; + if (newList.size() < m_modpacks_per_page) { + m_searchState = Finished; } else { - nextSearchOffset += m_modpacks_per_page; - searchState = CanPossiblyFetchMore; + m_nextSearchOffset += m_modpacks_per_page; + m_searchState = CanPossiblyFetchMore; } // When you have a Qt build with assertions turned on, proceeding here will abort the application if (newList.size() == 0) return; - beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + newList.size() - 1); - modpacks.append(newList); + beginInsertRows(QModelIndex(), m_modpacks.size(), m_modpacks.size() + newList.size() - 1); + m_modpacks.append(newList); endInsertRows(); } -void ModpackListModel::searchRequestForOneSucceeded(QJsonDocument& doc) +void ModpackListModel::searchRequestForOneSucceeded(ModPlatform::IndexedPack& pack) { - jobPtr.reset(); + m_jobPtr.reset(); - auto packObj = doc.object(); - - Modrinth::Modpack pack; - try { - Modrinth::loadIndexedPack(pack, packObj); - pack.id = Json::ensureString(packObj, "id", pack.id); - } catch (const JSONValidationError& e) { - qWarning() << "Error while loading mod from " << m_parent->debugName() << ": " << e.cause(); - return; - } - - beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + 1); - modpacks.append({ pack }); + beginInsertRows(QModelIndex(), m_modpacks.size(), m_modpacks.size() + 1); + m_modpacks.append(std::make_shared(pack)); endInsertRows(); } void ModpackListModel::searchRequestFailed(QString) { - auto failed_action = dynamic_cast(jobPtr.get())->getFailedActions().at(0); + auto failed_action = dynamic_cast(m_jobPtr.get())->getFailedActions().at(0); if (failed_action->replyStatusCode() == -1) { // Network error QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load modpacks.")); @@ -362,17 +322,17 @@ void ModpackListModel::searchRequestFailed(QString) .arg(m_parent->displayName()) .arg(tr("API version too old!\nPlease update %1!").arg(BuildConfig.LAUNCHER_DISPLAYNAME))); } - jobPtr.reset(); + m_jobPtr.reset(); - if (searchState == ResetRequested) { + if (m_searchState == ResetRequested) { beginResetModel(); - modpacks.clear(); + m_modpacks.clear(); endResetModel(); - nextSearchOffset = 0; + m_nextSearchOffset = 0; performPaginatedSearch(); } else { - searchState = Finished; + m_searchState = Finished; } } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index cdd5c4e79..7037f4745 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -37,7 +37,7 @@ #include -#include "modplatform/modrinth/ModrinthPackManifest.h" +#include "modplatform/ModIndex.h" #include "net/NetJob.h" #include "ui/pages/modplatform/modrinth/ModrinthPage.h" @@ -56,7 +56,7 @@ class ModpackListModel : public QAbstractListModel { ModpackListModel(ModrinthPage* parent); ~ModpackListModel() override = default; - inline auto rowCount(const QModelIndex& parent) const -> int override { return parent.isValid() ? 0 : modpacks.size(); }; + inline auto rowCount(const QModelIndex& parent) const -> int override { return parent.isValid() ? 0 : m_modpacks.size(); }; inline auto columnCount(const QModelIndex& parent) const -> int override { return parent.isValid() ? 0 : 1; }; inline auto flags(const QModelIndex& index) const -> Qt::ItemFlags override { return QAbstractListModel::flags(index); }; @@ -66,27 +66,27 @@ class ModpackListModel : public QAbstractListModel { auto data(const QModelIndex& index, int role) const -> QVariant override; bool setData(const QModelIndex& index, const QVariant& value, int role) override; - inline void setActiveJob(NetJob::Ptr ptr) { jobPtr = ptr; } + inline void setActiveJob(NetJob::Ptr ptr) { m_jobPtr = ptr; } /* Ask the API for more information */ void fetchMore(const QModelIndex& parent) override; void refresh(); void searchWithTerm(const QString& term, int sort, std::shared_ptr filter, bool filterChanged); - bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } - Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } + bool hasActiveSearchJob() const { return m_jobPtr && m_jobPtr->isRunning(); } + Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? m_jobPtr : nullptr; } void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); inline auto canFetchMore(const QModelIndex& parent) const -> bool override { - return parent.isValid() ? false : searchState == CanPossiblyFetchMore; + return parent.isValid() ? false : m_searchState == CanPossiblyFetchMore; }; public slots: - void searchRequestFinished(QJsonDocument& doc_all); + void searchRequestFinished(QList& doc_all); void searchRequestFailed(QString reason); - void searchRequestForOneSucceeded(QJsonDocument&); + void searchRequestForOneSucceeded(ModPlatform::IndexedPack&); protected slots: @@ -103,20 +103,20 @@ class ModpackListModel : public QAbstractListModel { protected: ModrinthPage* m_parent; - QList modpacks; + QList m_modpacks; LogoMap m_logoMap; - QMap waitingCallbacks; + QMap m_waitingCallbacks; QStringList m_failedLogos; QStringList m_loadingLogos; - QString currentSearchTerm; - QString currentSort; + QString m_currentSearchTerm; + QString m_currentSort; std::shared_ptr m_filter; - int nextSearchOffset = 0; - enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None; + int m_nextSearchOffset = 0; + enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } m_searchState = None; - Task::Ptr jobPtr; + Task::Ptr m_jobPtr; std::shared_ptr m_allResponse = std::make_shared(); QByteArray m_specific_response; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index d9004a1fc..768f2f492 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -36,6 +36,7 @@ #include "ModrinthPage.h" #include "Version.h" +#include "modplatform/ModIndex.h" #include "modplatform/modrinth/ModrinthAPI.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui_ModrinthPage.h" @@ -57,17 +58,17 @@ #include ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) - : QWidget(parent), ui(new Ui::ModrinthPage), dialog(dialog), m_fetch_progress(this, false) + : QWidget(parent), m_ui(new Ui::ModrinthPage), m_dialog(dialog), m_fetch_progress(this, false) { - ui->setupUi(this); + m_ui->setupUi(this); createFilterWidget(); - ui->searchEdit->installEventFilter(this); + m_ui->searchEdit->installEventFilter(this); m_model = new Modrinth::ModpackListModel(this); - ui->packView->setModel(m_model); + m_ui->packView->setModel(m_model); - ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + m_ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); m_search_timer.setTimerType(Qt::TimerType::CoarseTimer); m_search_timer.setSingleShot(true); @@ -78,30 +79,30 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) m_fetch_progress.setFixedHeight(24); m_fetch_progress.progressFormat(""); - ui->verticalLayout->insertWidget(1, &m_fetch_progress); + m_ui->verticalLayout->insertWidget(1, &m_fetch_progress); - ui->sortByBox->addItem(tr("Sort by Relevance")); - ui->sortByBox->addItem(tr("Sort by Total Downloads")); - ui->sortByBox->addItem(tr("Sort by Follows")); - ui->sortByBox->addItem(tr("Sort by Newest")); - ui->sortByBox->addItem(tr("Sort by Last Updated")); + m_ui->sortByBox->addItem(tr("Sort by Relevance")); + m_ui->sortByBox->addItem(tr("Sort by Total Downloads")); + m_ui->sortByBox->addItem(tr("Sort by Follows")); + m_ui->sortByBox->addItem(tr("Sort by Newest")); + m_ui->sortByBox->addItem(tr("Sort by Last Updated")); - connect(ui->sortByBox, &QComboBox::currentIndexChanged, this, &ModrinthPage::triggerSearch); - connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthPage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthPage::onVersionSelectionChanged); + connect(m_ui->sortByBox, &QComboBox::currentIndexChanged, this, &ModrinthPage::triggerSearch); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthPage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthPage::onVersionSelectionChanged); - ui->packView->setItemDelegate(new ProjectItemDelegate(this)); - ui->packDescription->setMetaEntry(metaEntryBase()); + m_ui->packView->setItemDelegate(new ProjectItemDelegate(this)); + m_ui->packDescription->setMetaEntry(metaEntryBase()); } ModrinthPage::~ModrinthPage() { - delete ui; + delete m_ui; } void ModrinthPage::retranslate() { - ui->retranslateUi(this); + m_ui->retranslateUi(this); } void ModrinthPage::openedImpl() @@ -113,7 +114,7 @@ void ModrinthPage::openedImpl() bool ModrinthPage::eventFilter(QObject* watched, QEvent* event) { - if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) { + if (watched == m_ui->searchEdit && event->type() == QEvent::KeyPress) { auto* keyEvent = reinterpret_cast(event); if (keyEvent->key() == Qt::Key_Return) { this->triggerSearch(); @@ -129,146 +130,108 @@ bool ModrinthPage::eventFilter(QObject* watched, QEvent* event) return QObject::eventFilter(watched, event); } -bool checkVersionFilters(const Modrinth::ModpackVersion& v, std::shared_ptr filter) -{ - if (!filter) - return true; - return ((!filter->loaders || !v.loaders || filter->loaders & v.loaders) && // loaders - (filter->releases.empty() || // releases - std::find(filter->releases.cbegin(), filter->releases.cend(), v.version_type) != filter->releases.cend()) && - filter->checkMcVersions({ v.gameVersion })); // gameVersion} -} - void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev) { - ui->versionSelectionBox->clear(); + m_ui->versionSelectionBox->clear(); if (!curr.isValid()) { if (isOpened) { - dialog->setSuggestedPack(); + m_dialog->setSuggestedPack(); } return; } - QVariant raw = m_model->data(curr, Qt::UserRole); - Q_ASSERT(raw.canConvert()); - current = raw.value(); - auto name = current.name; + m_current = m_model->data(curr, Qt::UserRole).value(); + auto name = m_current->name; - if (!current.extraInfoLoaded) { + if (!m_current->extraDataLoaded) { qDebug() << "Loading modrinth modpack information"; + ResourceAPI::Callback callbacks; - auto netJob = new NetJob(QString("Modrinth::PackInformation(%1)").arg(current.name), APPLICATION->network()); - auto response = std::make_shared(); - - QString id = current.id; - - netJob->addNetAction(Net::ApiDownload::makeByteArray(QString("%1/project/%2").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); - - connect(netJob, &NetJob::succeeded, this, [this, response, id, curr] { - if (id != current.id) { + auto id = m_current->addonId; + callbacks.on_fail = [this](QString reason, int) { + CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); + }; + callbacks.on_succeed = [this, id, curr](auto& pack) { + if (id != m_current->addonId) { return; // wrong request? } - QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Modrinth at " << parse_error.offset - << " reason: " << parse_error.errorString(); - qWarning() << *response; - return; - } - - auto obj = Json::requireObject(doc); - - try { - Modrinth::loadIndexedInfo(current, obj); - } catch (const JSONValidationError& e) { - qDebug() << *response; - qWarning() << "Error while reading modrinth modpack version: " << e.cause(); - } - - updateUI(); + *m_current = pack; QVariant current_updated; - current_updated.setValue(current); + current_updated.setValue(m_current); if (!m_model->setData(curr, current_updated, Qt::UserRole)) qWarning() << "Failed to cache extra info for the current pack!"; suggestCurrent(); - }); - connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); }); - connect(netJob, &NetJob::failed, - [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); - netJob->start(); + updateUI(); + }; + if (auto netJob = m_api.getProjectInfo({ { m_current->addonId } }, std::move(callbacks)); netJob) { + m_job = netJob; + m_job->start(); + } + } else updateUI(); - if (!current.versionsLoaded || m_filterWidget->changed()) { + if (!m_current->versionsLoaded || m_filterWidget->changed()) { qDebug() << "Loading modrinth modpack versions"; - auto netJob = new NetJob(QString("Modrinth::PackVersions(%1)").arg(current.name), APPLICATION->network()); - auto response = std::make_shared(); + ResourceAPI::Callback> callbacks{}; - QString id = current.id; - - netJob->addNetAction( - Net::ApiDownload::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); - - connect(netJob, &NetJob::succeeded, this, [this, response, id, curr] { - if (id != current.id) { - return; // wrong request? + auto addonId = m_current->addonId; + // Use default if no callbacks are set + callbacks.on_succeed = [this, curr, addonId](auto& doc) { + if (addonId != m_current->addonId) { + return; // wrong request } - QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Modrinth at " << parse_error.offset - << " reason: " << parse_error.errorString(); - qWarning() << *response; - return; - } - - try { - Modrinth::loadIndexedVersions(current, doc); - } catch (const JSONValidationError& e) { - qDebug() << *response; - qWarning() << "Error while reading modrinth modpack version: " << e.cause(); - } - auto pred = [this](const Modrinth::ModpackVersion& v) { return !checkVersionFilters(v, m_filterWidget->getFilter()); }; + m_current->versions = doc; + m_current->versionsLoaded = true; + auto pred = [this](const ModPlatform::IndexedVersion& v) { + if (auto filter = m_filterWidget->getFilter()) + return !filter->checkModpackFilters(v); + return false; + }; #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) - current.versions.removeIf(pred); + m_current->versions.removeIf(pred); #else - for (auto it = current.versions.begin(); it != current.versions.end();) - if (pred(*it)) - it = current.versions.erase(it); - else - ++it; + for (auto it = m_current->versions.begin(); it != m_current->versions.end();) + if (pred(*it)) + it = m_current->versions.erase(it); + else + ++it; #endif - for (const auto& version : current.versions) { - ui->versionSelectionBox->addItem(Modrinth::getVersionDisplayString(version), QVariant(version.id)); + for (const auto& version : m_current->versions) { + m_ui->versionSelectionBox->addItem(version.getVersionDisplayString(), QVariant(version.addonId)); } QVariant current_updated; - current_updated.setValue(current); + current_updated.setValue(m_current); if (!m_model->setData(curr, current_updated, Qt::UserRole)) qWarning() << "Failed to cache versions for the current pack!"; suggestCurrent(); - }); - connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); }); - connect(netJob, &NetJob::failed, - [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); - netJob->start(); + }; + callbacks.on_fail = [this](QString reason, int) { + CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); + }; + + auto netJob = m_api.getProjectVersions({ *m_current, {}, {}, ModPlatform::ResourceType::Modpack }, std::move(callbacks)); + + m_job2 = netJob; + m_job2->start(); } else { - for (auto version : current.versions) { - if (!version.name.contains(version.version)) - ui->versionSelectionBox->addItem(QString("%1 - %2").arg(version.name, version.version), QVariant(version.id)); + for (auto version : m_current->versions) { + if (!version.version.contains(version.version)) + m_ui->versionSelectionBox->addItem(QString("%1 - %2").arg(version.version, version.version_number), + QVariant(version.addonId)); else - ui->versionSelectionBox->addItem(version.name, QVariant(version.id)); + m_ui->versionSelectionBox->addItem(version.version, QVariant(version.addonId)); } suggestCurrent(); @@ -279,53 +242,64 @@ void ModrinthPage::updateUI() { QString text = ""; - if (current.extra.projectUrl.isEmpty()) - text = current.name; + if (m_current->websiteUrl.isEmpty()) + text = m_current->name; else - text = "" + current.name + ""; + text = "websiteUrl + "\">" + m_current->name + ""; - // TODO: Implement multiple authors with links - text += "
" + tr(" by ") + QString("%2").arg(std::get<1>(current.author).toString(), std::get<0>(current.author)); + if (!m_current->authors.empty()) { + auto authorToStr = [](ModPlatform::ModpackAuthor& author) { + if (author.url.isEmpty()) { + return author.name; + } + return QString("%2").arg(author.url, author.name); + }; + QStringList authorStrs; + for (auto& author : m_current->authors) { + authorStrs.push_back(authorToStr(author)); + } + text += "
" + tr(" by ") + authorStrs.join(", "); + } - if (current.extraInfoLoaded) { - if (current.extra.status == "archived") { + if (m_current->extraDataLoaded) { + if (m_current->extraData.status == "archived") { text += "

" + tr("This project has been archived. It will not receive any further updates unless the author decides " "to unarchive the project."); } - if (!current.extra.donate.isEmpty()) { + if (!m_current->extraData.donate.isEmpty()) { text += "

" + tr("Donate information: "); - auto donateToStr = [](Modrinth::DonationData& donate) -> QString { + auto donateToStr = [](ModPlatform::DonationData& donate) -> QString { return QString("%2").arg(donate.url, donate.platform); }; QStringList donates; - for (auto& donate : current.extra.donate) { + for (auto& donate : m_current->extraData.donate) { donates.append(donateToStr(donate)); } text += donates.join(", "); } - if (!current.extra.issuesUrl.isEmpty() || !current.extra.sourceUrl.isEmpty() || !current.extra.wikiUrl.isEmpty() || - !current.extra.discordUrl.isEmpty()) { + if (!m_current->extraData.issuesUrl.isEmpty() || !m_current->extraData.sourceUrl.isEmpty() || + !m_current->extraData.wikiUrl.isEmpty() || !m_current->extraData.discordUrl.isEmpty()) { text += "

" + tr("External links:") + "
"; } - if (!current.extra.issuesUrl.isEmpty()) - text += "- " + tr("Issues: %1").arg(current.extra.issuesUrl) + "
"; - if (!current.extra.wikiUrl.isEmpty()) - text += "- " + tr("Wiki: %1").arg(current.extra.wikiUrl) + "
"; - if (!current.extra.sourceUrl.isEmpty()) - text += "- " + tr("Source code: %1").arg(current.extra.sourceUrl) + "
"; - if (!current.extra.discordUrl.isEmpty()) - text += "- " + tr("Discord: %1").arg(current.extra.discordUrl) + "
"; + if (!m_current->extraData.issuesUrl.isEmpty()) + text += "- " + tr("Issues: %1").arg(m_current->extraData.issuesUrl) + "
"; + if (!m_current->extraData.wikiUrl.isEmpty()) + text += "- " + tr("Wiki: %1").arg(m_current->extraData.wikiUrl) + "
"; + if (!m_current->extraData.sourceUrl.isEmpty()) + text += "- " + tr("Source code: %1").arg(m_current->extraData.sourceUrl) + "
"; + if (!m_current->extraData.discordUrl.isEmpty()) + text += "- " + tr("Discord: %1").arg(m_current->extraData.discordUrl) + "
"; } text += "
"; - text += markdownToHTML(current.extra.body.toUtf8()); + text += markdownToHTML(m_current->extraData.body.toUtf8()); - ui->packDescription->setHtml(StringUtils::htmlListPatch(text + current.description)); - ui->packDescription->flush(); + m_ui->packDescription->setHtml(StringUtils::htmlListPatch(text + m_current->description)); + m_ui->packDescription->flush(); } void ModrinthPage::suggestCurrent() @@ -334,21 +308,21 @@ void ModrinthPage::suggestCurrent() return; } - if (selectedVersion.isEmpty()) { - dialog->setSuggestedPack(); + if (m_selectedVersion.isEmpty()) { + m_dialog->setSuggestedPack(); return; } - for (auto& ver : current.versions) { - if (ver.id == selectedVersion) { + for (auto& ver : m_current->versions) { + if (ver.addonId == m_selectedVersion) { QMap extra_info; - extra_info.insert("pack_id", current.id); - extra_info.insert("pack_version_id", ver.id); + extra_info.insert("pack_id", m_current->addonId.toString()); + extra_info.insert("pack_version_id", ver.fileId.toString()); - dialog->setSuggestedPack(current.name, ver.version, new InstanceImportTask(ver.download_url, this, std::move(extra_info))); - auto iconName = current.iconName; - m_model->getLogo(iconName, current.iconUrl.toString(), - [this, iconName](QString logo) { dialog->setSuggestedIconFromFile(logo, iconName); }); + m_dialog->setSuggestedPack(m_current->name, ver.version, new InstanceImportTask(ver.downloadUrl, this, std::move(extra_info))); + auto iconName = m_current->logoName; + m_model->getLogo(iconName, m_current->logoUrl, + [this, iconName](QString logo) { m_dialog->setSuggestedIconFromFile(logo, iconName); }); break; } @@ -357,46 +331,46 @@ void ModrinthPage::suggestCurrent() void ModrinthPage::triggerSearch() { - ui->packView->selectionModel()->setCurrentIndex({}, QItemSelectionModel::SelectionFlag::ClearAndSelect); - ui->packView->clearSelection(); - ui->packDescription->clear(); - ui->versionSelectionBox->clear(); + m_ui->packView->selectionModel()->setCurrentIndex({}, QItemSelectionModel::SelectionFlag::ClearAndSelect); + m_ui->packView->clearSelection(); + m_ui->packDescription->clear(); + m_ui->versionSelectionBox->clear(); bool filterChanged = m_filterWidget->changed(); - m_model->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), m_filterWidget->getFilter(), filterChanged); + m_model->searchWithTerm(m_ui->searchEdit->text(), m_ui->sortByBox->currentIndex(), m_filterWidget->getFilter(), filterChanged); m_fetch_progress.watch(m_model->activeSearchJob().get()); } void ModrinthPage::onVersionSelectionChanged(int index) { if (index == -1) { - selectedVersion = ""; + m_selectedVersion = ""; return; } - selectedVersion = ui->versionSelectionBox->itemData(index).toString(); + m_selectedVersion = m_ui->versionSelectionBox->itemData(index).toString(); suggestCurrent(); } void ModrinthPage::setSearchTerm(QString term) { - ui->searchEdit->setText(term); + m_ui->searchEdit->setText(term); } QString ModrinthPage::getSerachTerm() const { - return ui->searchEdit->text(); + return m_ui->searchEdit->text(); } void ModrinthPage::createFilterWidget() { auto widget = ModFilterWidget::create(nullptr, true); m_filterWidget.swap(widget); - auto old = ui->splitter->replaceWidget(0, m_filterWidget.get()); + auto old = m_ui->splitter->replaceWidget(0, m_filterWidget.get()); // because we replaced the widget we also need to delete it if (old) { delete old; } - connect(ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); }); + connect(m_ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); }); connect(m_filterWidget.get(), &ModFilterWidget::filterChanged, this, &ModrinthPage::triggerSearch); auto response = std::make_shared(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index 77cc173dd..600500c6d 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -37,9 +37,10 @@ #pragma once #include "Application.h" +#include "modplatform/ModIndex.h" +#include "modplatform/modrinth/ModrinthAPI.h" #include "ui/dialogs/NewInstanceDialog.h" -#include "modplatform/modrinth/ModrinthPackManifest.h" #include "ui/pages/modplatform/ModpackProviderBasePage.h" #include "ui/widgets/ModFilterWidget.h" #include "ui/widgets/ProgressWidget.h" @@ -67,10 +68,10 @@ class ModrinthPage : public QWidget, public ModpackProviderBasePage { QString id() const override { return "modrinth"; } QString helpPage() const override { return "Modrinth-platform"; } - inline auto debugName() const -> QString { return "Modrinth"; } - inline auto metaEntryBase() const -> QString { return "ModrinthModpacks"; }; + inline QString debugName() const { return "Modrinth"; } + inline QString metaEntryBase() const { return "ModrinthModpacks"; }; - auto getCurrent() -> Modrinth::Modpack& { return current; } + ModPlatform::IndexedPack::Ptr getCurrent() { return m_current; } void suggestCurrent(); void updateUI(); @@ -91,12 +92,12 @@ class ModrinthPage : public QWidget, public ModpackProviderBasePage { void createFilterWidget(); private: - Ui::ModrinthPage* ui; - NewInstanceDialog* dialog; + Ui::ModrinthPage* m_ui; + NewInstanceDialog* m_dialog; Modrinth::ModpackListModel* m_model; - Modrinth::Modpack current; - QString selectedVersion; + ModPlatform::IndexedPack::Ptr m_current; + QString m_selectedVersion; ProgressWidget m_fetch_progress; @@ -105,4 +106,8 @@ class ModrinthPage : public QWidget, public ModpackProviderBasePage { std::unique_ptr m_filterWidget; Task::Ptr m_categoriesTask; + + ModrinthAPI m_api; + Task::Ptr m_job; + Task::Ptr m_job2; }; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp deleted file mode 100644 index 91e9ad791..000000000 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// SPDX-FileCopyrightText: 2023 flowln -// -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Sefa Eyeoglu - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "ModrinthResourceModels.h" - -#include "modplatform/modrinth/ModrinthAPI.h" -#include "modplatform/modrinth/ModrinthPackIndex.h" - -namespace ResourceDownload { - -ModrinthModModel::ModrinthModModel(BaseInstance& base) : ModModel(base, new ModrinthAPI) {} - -void ModrinthModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadIndexedPack(m, obj); -} - -void ModrinthModModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadExtraPackData(m, obj); -} - -void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - ::Modrinth::loadIndexedPackVersions(m, arr); -} - -auto ModrinthModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion -{ - return ::Modrinth::loadDependencyVersions(m, arr, &m_base_instance); -} - -auto ModrinthModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return obj.object().value("hits").toArray(); -} - -ModrinthResourcePackModel::ModrinthResourcePackModel(const BaseInstance& base) : ResourcePackResourceModel(base, new ModrinthAPI) {} - -void ModrinthResourcePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadIndexedPack(m, obj); -} - -void ModrinthResourcePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadExtraPackData(m, obj); -} - -void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - ::Modrinth::loadIndexedPackVersions(m, arr); -} - -auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return obj.object().value("hits").toArray(); -} - -ModrinthTexturePackModel::ModrinthTexturePackModel(const BaseInstance& base) : TexturePackResourceModel(base, new ModrinthAPI) {} - -void ModrinthTexturePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadIndexedPack(m, obj); -} - -void ModrinthTexturePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadExtraPackData(m, obj); -} - -void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - ::Modrinth::loadIndexedPackVersions(m, arr); -} - -auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return obj.object().value("hits").toArray(); -} - -ModrinthShaderPackModel::ModrinthShaderPackModel(const BaseInstance& base) : ShaderPackResourceModel(base, new ModrinthAPI) {} - -void ModrinthShaderPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadIndexedPack(m, obj); -} - -void ModrinthShaderPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadExtraPackData(m, obj); -} - -void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - ::Modrinth::loadIndexedPackVersions(m, arr); -} - -auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return obj.object().value("hits").toArray(); -} - -ModrinthDataPackModel::ModrinthDataPackModel(const BaseInstance& base) : DataPackResourceModel(base, new ModrinthAPI) {} - -void ModrinthDataPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadIndexedPack(m, obj); -} - -void ModrinthDataPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) -{ - ::Modrinth::loadExtraPackData(m, obj); -} - -void ModrinthDataPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) -{ - ::Modrinth::loadIndexedPackVersions(m, arr); -} - -auto ModrinthDataPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray -{ - return obj.object().value("hits").toArray(); -} - - -} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h deleted file mode 100644 index 7f68ed47d..000000000 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-FileCopyrightText: 2023 flowln -// -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Sefa Eyeoglu - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "ui/pages/modplatform/DataPackModel.h" -#include "ui/pages/modplatform/ModModel.h" -#include "ui/pages/modplatform/ResourcePackModel.h" -#include "ui/pages/modplatform/modrinth/ModrinthResourcePages.h" - -namespace ResourceDownload { - -class ModrinthModModel : public ModModel { - Q_OBJECT - - public: - ModrinthModModel(BaseInstance&); - ~ModrinthModModel() override = default; - - private: - QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } - - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; - - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; -}; - -class ModrinthResourcePackModel : public ResourcePackResourceModel { - Q_OBJECT - - public: - ModrinthResourcePackModel(const BaseInstance&); - ~ModrinthResourcePackModel() override = default; - - private: - QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } - - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; -}; - -class ModrinthTexturePackModel : public TexturePackResourceModel { - Q_OBJECT - - public: - ModrinthTexturePackModel(const BaseInstance&); - ~ModrinthTexturePackModel() override = default; - - private: - QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } - - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; -}; - -class ModrinthShaderPackModel : public ShaderPackResourceModel { - Q_OBJECT - - public: - ModrinthShaderPackModel(const BaseInstance&); - ~ModrinthShaderPackModel() override = default; - - private: - QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } - - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; -}; - -class ModrinthDataPackModel : public DataPackResourceModel { - Q_OBJECT - - public: - ModrinthDataPackModel(const BaseInstance&); - ~ModrinthDataPackModel() override = default; - - private: - QString debugName() const override { return Modrinth::debugName() + " (Model)"; } - QString metaEntryBase() const override { return Modrinth::metaEntryBase(); } - - void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; - void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - - auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; -}; - -} // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index aca71cde5..32296316f 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -37,19 +37,18 @@ */ #include "ModrinthResourcePages.h" +#include "ui/pages/modplatform/DataPackModel.h" #include "ui_ResourcePage.h" #include "modplatform/modrinth/ModrinthAPI.h" #include "ui/dialogs/ResourceDownloadDialog.h" -#include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h" - namespace ResourceDownload { ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ModPage(dialog, instance) { - m_model = new ModrinthModModel(instance); + m_model = new ModModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); m_ui->packView->setModel(m_model); addSortings(); @@ -67,7 +66,7 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instan ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) : ResourcePackResourcePage(dialog, instance) { - m_model = new ModrinthResourcePackModel(instance); + m_model = new ResourcePackResourceModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); m_ui->packView->setModel(m_model); addSortings(); @@ -85,7 +84,7 @@ ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* d ModrinthTexturePackPage::ModrinthTexturePackPage(TexturePackDownloadDialog* dialog, BaseInstance& instance) : TexturePackResourcePage(dialog, instance) { - m_model = new ModrinthTexturePackModel(instance); + m_model = new TexturePackResourceModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); m_ui->packView->setModel(m_model); addSortings(); @@ -103,7 +102,7 @@ ModrinthTexturePackPage::ModrinthTexturePackPage(TexturePackDownloadDialog* dial ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) : ShaderPackResourcePage(dialog, instance) { - m_model = new ModrinthShaderPackModel(instance); + m_model = new ShaderPackResourceModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); m_ui->packView->setModel(m_model); addSortings(); @@ -118,10 +117,9 @@ ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, m_ui->packDescription->setMetaEntry(metaEntryBase()); } -ModrinthDataPackPage::ModrinthDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance) - : DataPackResourcePage(dialog, instance) +ModrinthDataPackPage::ModrinthDataPackPage(DataPackDownloadDialog* dialog, BaseInstance& instance) : DataPackResourcePage(dialog, instance) { - m_model = new ModrinthDataPackModel(instance); + m_model = new DataPackResourceModel(instance, new ModrinthAPI(), Modrinth::debugName(), Modrinth::metaEntryBase()); m_ui->packView->setModel(m_model); addSortings(); diff --git a/launcher/ui/widgets/MinecraftSettingsWidget.cpp b/launcher/ui/widgets/MinecraftSettingsWidget.cpp index 7cd84c8bb..9c8e2b405 100644 --- a/launcher/ui/widgets/MinecraftSettingsWidget.cpp +++ b/launcher/ui/widgets/MinecraftSettingsWidget.cpp @@ -36,6 +36,7 @@ */ #include "MinecraftSettingsWidget.h" +#include "modplatform/ModIndex.h" #include "ui_MinecraftSettingsWidget.h" #include diff --git a/launcher/ui/widgets/ModFilterWidget.h b/launcher/ui/widgets/ModFilterWidget.h index 8a858fd30..f00b98eb0 100644 --- a/launcher/ui/widgets/ModFilterWidget.h +++ b/launcher/ui/widgets/ModFilterWidget.h @@ -81,6 +81,14 @@ class ModFilterWidget : public QTabWidget { return versions.empty(); } + + bool checkModpackFilters(const ModPlatform::IndexedVersion& v) + { + return ((!loaders || !v.loaders || loaders & v.loaders) && // loaders + (releases.empty() || // releases + std::find(releases.cbegin(), releases.cend(), v.version_type) != releases.cend()) && + checkMcVersions({ v.mcVersion })); // gameVersion} + } }; static std::unique_ptr create(MinecraftInstance* instance, bool extended); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 31b887ff1..2165cd03d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,9 +21,6 @@ ecm_add_test(ResourceFolderModel_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_V ecm_add_test(ResourcePackParse_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test TEST_NAME ResourcePackParse) -ecm_add_test(ResourceModel_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test - TEST_NAME ResourceModel) - ecm_add_test(TexturePackParse_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test TEST_NAME TexturePackParse) diff --git a/tests/DummyResourceAPI.h b/tests/DummyResourceAPI.h deleted file mode 100644 index d5ae1392d..000000000 --- a/tests/DummyResourceAPI.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include - -#include - -class SearchTask : public Task { - Q_OBJECT - - public: - void executeTask() override { emitSucceeded(); } -}; - -class DummyResourceAPI : public ResourceAPI { - public: - static auto searchRequestResult() - { - static QByteArray json_response = - "{\"hits\":[" - "{" - "\"author\":\"flowln\"," - "\"description\":\"the bestest mod\"," - "\"project_id\":\"something\"," - "\"project_type\":\"mod\"," - "\"slug\":\"bip_bop\"," - "\"title\":\"AAAAAAAA\"," - "\"versions\":[\"2.71\"]" - "}" - "]}"; - - return QJsonDocument::fromJson(json_response); - } - - DummyResourceAPI() : ResourceAPI() {} - auto getSortingMethods() const -> QList override { return {}; } - - Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&& callbacks) const override - { - auto task = makeShared(); - QObject::connect(task.get(), &Task::succeeded, [callbacks] { - auto json = searchRequestResult(); - callbacks.on_succeed(json); - }); - return task; - } -}; diff --git a/tests/ResourceModel_test.cpp b/tests/ResourceModel_test.cpp deleted file mode 100644 index c4ea1a20f..000000000 --- a/tests/ResourceModel_test.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include - -#include - -#include - -#include "DummyResourceAPI.h" - -using ResourceDownload::ResourceModel; - -#define EXEC_TASK(EXEC) \ - QEventLoop loop; \ - \ - connect(model, &ResourceModel::dataChanged, &loop, &QEventLoop::quit); \ - \ - QTimer expire_timer; \ - expire_timer.callOnTimeout(&loop, &QEventLoop::quit); \ - expire_timer.setSingleShot(true); \ - expire_timer.start(4000); \ - \ - EXEC; \ - if (model->hasActiveSearchJob()) \ - loop.exec(); \ - \ - QVERIFY2(expire_timer.isActive(), "Timer has expired. The search never finished."); \ - expire_timer.stop(); \ - \ - disconnect(model, nullptr, &loop, nullptr) - -class ResourceModelTest; - -class DummyResourceModel : public ResourceModel { - Q_OBJECT - - friend class ResourceModelTest; - - public: - DummyResourceModel() : ResourceModel(new DummyResourceAPI) {} - ~DummyResourceModel() {} - - auto metaEntryBase() const -> QString override { return ""; } - - ResourceAPI::SearchArgs createSearchArguments() override { return {}; } - ResourceAPI::VersionSearchArgs createVersionsArguments(const QModelIndex&) override { return {}; } - ResourceAPI::ProjectInfoArgs createInfoArguments(const QModelIndex&) override { return {}; } - - QJsonArray documentToArray(QJsonDocument& doc) const override { return doc.object().value("hits").toArray(); } - - void loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) override - { - pack.authors.append({ Json::requireString(obj, "author"), "" }); - pack.description = Json::requireString(obj, "description"); - pack.addonId = Json::requireString(obj, "project_id"); - } -}; - -class ResourceModelTest : public QObject { - Q_OBJECT - private slots: - void test_abstract_item_model() - { - auto dummy = DummyResourceModel(); - auto tester = QAbstractItemModelTester(&dummy); - } - - void test_search() - { - auto model = new DummyResourceModel; - - QVERIFY(model->m_packs.isEmpty()); - - EXEC_TASK(model->search()); - - QVERIFY(model->m_packs.size() == 1); - QVERIFY(model->m_search_state == DummyResourceModel::SearchState::Finished); - - auto processed_pack = model->m_packs.at(0); - auto search_json = DummyResourceAPI::searchRequestResult(); - auto processed_response = model->documentToArray(search_json).first().toObject(); - - QVERIFY(processed_pack->addonId.toString() == Json::requireString(processed_response, "project_id")); - QVERIFY(processed_pack->description == Json::requireString(processed_response, "description")); - QVERIFY(processed_pack->authors.first().name == Json::requireString(processed_response, "author")); - - delete model; - } -}; - -QTEST_GUILESS_MAIN(ResourceModelTest) - -#include "ResourceModel_test.moc" - -#include "moc_DummyResourceAPI.cpp" From 5ef61aa445b6d5c3986bb1bec60ddfa80007928a Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 17 Sep 2025 10:30:00 +0100 Subject: [PATCH 114/118] Make BaseVersion const-correct in order to remove const-cast from Meta::Version Signed-off-by: TheKodeToad --- launcher/BaseVersion.h | 8 ++++---- launcher/java/JavaInstall.cpp | 10 +++++----- launcher/java/JavaInstall.h | 14 +++++++------- launcher/java/JavaMetadata.cpp | 10 +++++----- launcher/java/JavaMetadata.h | 14 +++++++------- launcher/meta/Version.cpp | 6 +++--- launcher/meta/Version.h | 4 ++-- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/launcher/BaseVersion.h b/launcher/BaseVersion.h index 2837ff3a9..02a7212e5 100644 --- a/launcher/BaseVersion.h +++ b/launcher/BaseVersion.h @@ -30,21 +30,21 @@ class BaseVersion { * A string used to identify this version in config files. * This should be unique within the version list or shenanigans will occur. */ - virtual QString descriptor() = 0; + virtual QString descriptor() const = 0; /*! * The name of this version as it is displayed to the user. * For example: "1.5.1" */ - virtual QString name() = 0; + virtual QString name() const = 0; /*! * This should return a string that describes * the kind of version this is (Stable, Beta, Snapshot, whatever) */ virtual QString typeString() const = 0; - virtual bool operator<(BaseVersion& a) { return name() < a.name(); } - virtual bool operator>(BaseVersion& a) { return name() > a.name(); } + virtual bool operator<(BaseVersion& a) const { return name() < a.name(); } + virtual bool operator>(BaseVersion& a) const { return name() > a.name(); } }; Q_DECLARE_METATYPE(BaseVersion::Ptr) diff --git a/launcher/java/JavaInstall.cpp b/launcher/java/JavaInstall.cpp index 8e97e0e14..30cb77e08 100644 --- a/launcher/java/JavaInstall.cpp +++ b/launcher/java/JavaInstall.cpp @@ -21,7 +21,7 @@ #include "BaseVersion.h" #include "StringUtils.h" -bool JavaInstall::operator<(const JavaInstall& rhs) +bool JavaInstall::operator<(const JavaInstall& rhs) const { auto archCompare = StringUtils::naturalCompare(arch, rhs.arch, Qt::CaseInsensitive); if (archCompare != 0) @@ -35,17 +35,17 @@ bool JavaInstall::operator<(const JavaInstall& rhs) return StringUtils::naturalCompare(path, rhs.path, Qt::CaseInsensitive) < 0; } -bool JavaInstall::operator==(const JavaInstall& rhs) +bool JavaInstall::operator==(const JavaInstall& rhs) const { return arch == rhs.arch && id == rhs.id && path == rhs.path; } -bool JavaInstall::operator>(const JavaInstall& rhs) +bool JavaInstall::operator>(const JavaInstall& rhs) const { return (!operator<(rhs)) && (!operator==(rhs)); } -bool JavaInstall::operator<(BaseVersion& a) +bool JavaInstall::operator<(BaseVersion& a) const { try { return operator<(dynamic_cast(a)); @@ -54,7 +54,7 @@ bool JavaInstall::operator<(BaseVersion& a) } } -bool JavaInstall::operator>(BaseVersion& a) +bool JavaInstall::operator>(BaseVersion& a) const { try { return operator>(dynamic_cast(a)); diff --git a/launcher/java/JavaInstall.h b/launcher/java/JavaInstall.h index 7d8d392fa..d8fd477fd 100644 --- a/launcher/java/JavaInstall.h +++ b/launcher/java/JavaInstall.h @@ -24,17 +24,17 @@ struct JavaInstall : public BaseVersion { JavaInstall() {} JavaInstall(QString id, QString arch, QString path) : id(id), arch(arch), path(path) {} - virtual QString descriptor() override { return id.toString(); } + virtual QString descriptor() const override { return id.toString(); } - virtual QString name() override { return id.toString(); } + virtual QString name() const override { return id.toString(); } virtual QString typeString() const override { return arch; } - virtual bool operator<(BaseVersion& a) override; - virtual bool operator>(BaseVersion& a) override; - bool operator<(const JavaInstall& rhs); - bool operator==(const JavaInstall& rhs); - bool operator>(const JavaInstall& rhs); + virtual bool operator<(BaseVersion& a) const override; + virtual bool operator>(BaseVersion& a) const override; + bool operator<(const JavaInstall& rhs) const; + bool operator==(const JavaInstall& rhs) const; + bool operator>(const JavaInstall& rhs) const; JavaVersion id; QString arch; diff --git a/launcher/java/JavaMetadata.cpp b/launcher/java/JavaMetadata.cpp index 2d68f55c8..d4da95457 100644 --- a/launcher/java/JavaMetadata.cpp +++ b/launcher/java/JavaMetadata.cpp @@ -78,7 +78,7 @@ MetadataPtr parseJavaMeta(const QJsonObject& in) return meta; } -bool Metadata::operator<(const Metadata& rhs) +bool Metadata::operator<(const Metadata& rhs) const { auto id = version; if (id < rhs.version) { @@ -97,17 +97,17 @@ bool Metadata::operator<(const Metadata& rhs) return StringUtils::naturalCompare(m_name, rhs.m_name, Qt::CaseInsensitive) < 0; } -bool Metadata::operator==(const Metadata& rhs) +bool Metadata::operator==(const Metadata& rhs) const { return version == rhs.version && m_name == rhs.m_name; } -bool Metadata::operator>(const Metadata& rhs) +bool Metadata::operator>(const Metadata& rhs) const { return (!operator<(rhs)) && (!operator==(rhs)); } -bool Metadata::operator<(BaseVersion& a) +bool Metadata::operator<(BaseVersion& a) const { try { return operator<(dynamic_cast(a)); @@ -116,7 +116,7 @@ bool Metadata::operator<(BaseVersion& a) } } -bool Metadata::operator>(BaseVersion& a) +bool Metadata::operator>(BaseVersion& a) const { try { return operator>(dynamic_cast(a)); diff --git a/launcher/java/JavaMetadata.h b/launcher/java/JavaMetadata.h index 77a42fd78..2e569ee39 100644 --- a/launcher/java/JavaMetadata.h +++ b/launcher/java/JavaMetadata.h @@ -32,17 +32,17 @@ enum class DownloadType { Manifest, Archive, Unknown }; class Metadata : public BaseVersion { public: - virtual QString descriptor() override { return version.toString(); } + virtual QString descriptor() const override { return version.toString(); } - virtual QString name() override { return m_name; } + virtual QString name() const override { return m_name; } virtual QString typeString() const override { return vendor; } - virtual bool operator<(BaseVersion& a) override; - virtual bool operator>(BaseVersion& a) override; - bool operator<(const Metadata& rhs); - bool operator==(const Metadata& rhs); - bool operator>(const Metadata& rhs); + virtual bool operator<(BaseVersion& a) const override; + virtual bool operator>(BaseVersion& a) const override; + bool operator<(const Metadata& rhs) const; + bool operator==(const Metadata& rhs) const; + bool operator>(const Metadata& rhs) const; QString m_name; QString vendor; diff --git a/launcher/meta/Version.cpp b/launcher/meta/Version.cpp index 74e71e91c..ce9a9cc8a 100644 --- a/launcher/meta/Version.cpp +++ b/launcher/meta/Version.cpp @@ -21,11 +21,11 @@ Meta::Version::Version(const QString& uid, const QString& version) : BaseVersion(), m_uid(uid), m_version(version) {} -QString Meta::Version::descriptor() +QString Meta::Version::descriptor() const { return m_version; } -QString Meta::Version::name() +QString Meta::Version::name() const { if (m_data) return m_data->name; @@ -88,7 +88,7 @@ QString Meta::Version::localFilename() const ::Version Meta::Version::toComparableVersion() const { - return { const_cast(this)->descriptor() }; + return { descriptor() }; } void Meta::Version::setType(const QString& type) diff --git a/launcher/meta/Version.h b/launcher/meta/Version.h index 6bddbf473..a2bbc6176 100644 --- a/launcher/meta/Version.h +++ b/launcher/meta/Version.h @@ -40,8 +40,8 @@ class Version : public QObject, public BaseVersion, public BaseEntity { explicit Version(const QString& uid, const QString& version); virtual ~Version() = default; - QString descriptor() override; - QString name() override; + QString descriptor() const override; + QString name() const override; QString typeString() const override; QString uid() const { return m_uid; } From 24726ea62167f349557638ed9fb8513b72d1c94c Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 17 Sep 2025 10:50:54 +0100 Subject: [PATCH 115/118] Avoid const-cast in WorldList - subclass is unnecessary and result->formats() is correct Signed-off-by: TheKodeToad --- launcher/minecraft/WorldList.cpp | 52 ++++++++++---------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp index 6a821ba60..059feabde 100644 --- a/launcher/minecraft/WorldList.cpp +++ b/launcher/minecraft/WorldList.cpp @@ -36,6 +36,7 @@ #include "WorldList.h" #include +#include #include #include #include @@ -301,50 +302,31 @@ QStringList WorldList::mimeTypes() const return types; } -class WorldMimeData : public QMimeData { - Q_OBJECT - - public: - WorldMimeData(QList worlds) { m_worlds = worlds; } - QStringList formats() const { return QMimeData::formats() << "text/uri-list"; } - - protected: - QVariant retrieveData(const QString& mimetype, QMetaType type) const - { - QList urls; - for (auto& world : m_worlds) { - if (!world.isValid() || !world.isOnFS()) - continue; - QString worldPath = world.container().absoluteFilePath(); - qDebug() << worldPath; - urls.append(QUrl::fromLocalFile(worldPath)); - } - const_cast(this)->setUrls(urls); - return QMimeData::retrieveData(mimetype, type); - } - - private: - QList m_worlds; -}; - QMimeData* WorldList::mimeData(const QModelIndexList& indexes) const { - if (indexes.size() == 0) - return new QMimeData(); + QList urls; - QList worlds_; for (auto idx : indexes) { if (idx.column() != 0) continue; + int row = idx.row(); if (row < 0 || row >= this->m_worlds.size()) continue; - worlds_.append(this->m_worlds[row]); + + const World& world = m_worlds[row]; + + if (!world.isValid() || !world.isOnFS()) + continue; + + QString worldPath = world.container().absoluteFilePath(); + qDebug() << worldPath; + urls.append(QUrl::fromLocalFile(worldPath)); } - if (!worlds_.size()) { - return new QMimeData(); - } - return new WorldMimeData(worlds_); + + auto result = new QMimeData(); + result->setUrls(urls); + return result; } Qt::ItemFlags WorldList::flags(const QModelIndex& index) const @@ -453,5 +435,3 @@ void WorldList::loadWorldsAsync() }); } } - -#include "WorldList.moc" From 7c9c9432dd2a5aa9a8027b35e2e5dafa5f3562f6 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 17 Sep 2025 11:24:10 +0100 Subject: [PATCH 116/118] Remove pointless const_cast in ProgressWidget Signed-off-by: TheKodeToad --- launcher/ui/widgets/ProgressWidget.cpp | 6 +++--- launcher/ui/widgets/ProgressWidget.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/launcher/ui/widgets/ProgressWidget.cpp b/launcher/ui/widgets/ProgressWidget.cpp index 9181de7f8..69c7e6f17 100644 --- a/launcher/ui/widgets/ProgressWidget.cpp +++ b/launcher/ui/widgets/ProgressWidget.cpp @@ -39,7 +39,7 @@ void ProgressWidget::progressFormat(QString format) m_bar->setFormat(format); } -void ProgressWidget::watch(const Task* task) +void ProgressWidget::watch(Task* task) { if (!task) return; @@ -61,11 +61,11 @@ void ProgressWidget::watch(const Task* task) connect(m_task, &Task::started, this, &ProgressWidget::show); } -void ProgressWidget::start(const Task* task) +void ProgressWidget::start(Task* task) { watch(task); if (!m_task->isRunning()) - QMetaObject::invokeMethod(const_cast(m_task), "start", Qt::QueuedConnection); + QMetaObject::invokeMethod(m_task, "start", Qt::QueuedConnection); } bool ProgressWidget::exec(std::shared_ptr task) diff --git a/launcher/ui/widgets/ProgressWidget.h b/launcher/ui/widgets/ProgressWidget.h index b0458f335..4d9097b8a 100644 --- a/launcher/ui/widgets/ProgressWidget.h +++ b/launcher/ui/widgets/ProgressWidget.h @@ -27,10 +27,10 @@ class ProgressWidget : public QWidget { public slots: /** Watch the progress of a task. */ - void watch(const Task* task); + void watch(Task* task); /** Watch the progress of a task, and start it if needed */ - void start(const Task* task); + void start(Task* task); /** Blocking way of waiting for a task to finish. */ bool exec(std::shared_ptr task); @@ -50,7 +50,7 @@ class ProgressWidget : public QWidget { private: QLabel* m_label = nullptr; QProgressBar* m_bar = nullptr; - const Task* m_task = nullptr; + Task* m_task = nullptr; bool m_hide_if_inactive = false; }; From cd4f119e4b73256464c8db42ad7d7abfc8e27a36 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 19 Sep 2025 00:03:22 +0100 Subject: [PATCH 117/118] Replace getThemedIcon with APPLICATION->logo() Signed-off-by: TheKodeToad --- launcher/Application.cpp | 7 ++----- launcher/Application.h | 2 +- launcher/VersionProxyModel.cpp | 6 +++--- launcher/minecraft/ShortcutUtils.cpp | 2 +- launcher/minecraft/mod/DataPackFolderModel.cpp | 3 +-- launcher/minecraft/mod/ModFolderModel.cpp | 4 +--- launcher/minecraft/mod/ResourceFolderModel.cpp | 5 ++--- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 3 +-- launcher/minecraft/mod/TexturePackFolderModel.cpp | 6 +----- launcher/ui/MainWindow.cpp | 12 ++++++------ launcher/ui/ViewLogWindow.cpp | 2 +- launcher/ui/dialogs/AboutDialog.cpp | 2 +- launcher/ui/dialogs/CreateShortcutDialog.cpp | 3 +-- launcher/ui/dialogs/InstallLoaderDialog.cpp | 2 +- launcher/ui/dialogs/NewInstanceDialog.cpp | 2 +- launcher/ui/dialogs/ProfileSetupDialog.cpp | 6 +++--- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 +- launcher/ui/dialogs/ReviewMessageBox.cpp | 4 +--- launcher/ui/dialogs/UpdateAvailableDialog.cpp | 3 +-- launcher/ui/java/InstallJavaDialog.cpp | 2 +- launcher/ui/pages/global/APIPage.h | 3 +-- launcher/ui/pages/global/AccountListPage.h | 5 ++--- launcher/ui/pages/global/AppearancePage.h | 3 +-- launcher/ui/pages/global/ExternalToolsPage.h | 5 ++--- launcher/ui/pages/global/JavaPage.h | 3 +-- launcher/ui/pages/global/LanguagePage.cpp | 1 + launcher/ui/pages/global/LanguagePage.h | 3 +-- launcher/ui/pages/global/LauncherPage.h | 3 +-- launcher/ui/pages/global/MinecraftPage.h | 3 +-- launcher/ui/pages/global/ProxyPage.h | 3 +-- launcher/ui/pages/instance/DataPackPage.h | 2 +- launcher/ui/pages/instance/GameOptionsPage.h | 3 +-- launcher/ui/pages/instance/InstanceSettingsPage.h | 3 +-- launcher/ui/pages/instance/LogPage.h | 3 +-- launcher/ui/pages/instance/ManagedPackPage.cpp | 2 +- launcher/ui/pages/instance/ModFolderPage.h | 6 +++--- launcher/ui/pages/instance/NotesPage.h | 5 ++--- launcher/ui/pages/instance/OtherLogsPage.h | 2 +- launcher/ui/pages/instance/ResourcePackPage.h | 2 +- launcher/ui/pages/instance/ScreenshotsPage.cpp | 2 +- launcher/ui/pages/instance/ScreenshotsPage.h | 3 +-- launcher/ui/pages/instance/ServersPage.cpp | 3 ++- launcher/ui/pages/instance/ServersPage.h | 4 ++-- launcher/ui/pages/instance/ShaderPackPage.h | 2 +- launcher/ui/pages/instance/TexturePackPage.h | 2 +- launcher/ui/pages/instance/VersionPage.cpp | 6 +++--- launcher/ui/pages/instance/WorldListPage.cpp | 4 ++-- launcher/ui/pages/instance/WorldListPage.h | 3 +-- launcher/ui/pages/modplatform/CustomPage.h | 4 ++-- launcher/ui/pages/modplatform/ImportPage.h | 3 +-- launcher/ui/pages/modplatform/ResourceModel.cpp | 2 +- .../ui/pages/modplatform/atlauncher/AtlListModel.cpp | 2 +- launcher/ui/pages/modplatform/atlauncher/AtlPage.h | 3 +-- launcher/ui/pages/modplatform/flame/FlameModel.cpp | 2 +- launcher/ui/pages/modplatform/flame/FlamePage.h | 3 +-- .../ui/pages/modplatform/flame/FlameResourcePages.h | 5 +---- .../ui/pages/modplatform/import_ftb/ImportFTBPage.h | 3 +-- .../ui/pages/modplatform/legacy_ftb/ListModel.cpp | 2 +- launcher/ui/pages/modplatform/legacy_ftb/Page.h | 3 +-- .../ui/pages/modplatform/modrinth/ModrinthModel.cpp | 3 ++- .../ui/pages/modplatform/modrinth/ModrinthPage.h | 3 +-- .../modplatform/modrinth/ModrinthResourcePages.h | 4 +--- .../ui/pages/modplatform/technic/TechnicModel.cpp | 2 +- launcher/ui/pages/modplatform/technic/TechnicPage.h | 3 +-- launcher/ui/widgets/JavaWizardWidget.cpp | 8 ++++---- launcher/ui/widgets/MinecraftSettingsWidget.cpp | 2 +- launcher/ui/widgets/PageContainer.cpp | 2 +- 67 files changed, 93 insertions(+), 133 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index a8bfd52e3..dbf55f425 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1489,12 +1489,9 @@ std::shared_ptr Application::javalist() return m_javalist; } -QIcon Application::getThemedIcon(const QString& name) +QIcon Application::logo() { - if (name == "logo") { - return QIcon(":/" + BuildConfig.LAUNCHER_SVGFILENAME); - } - return QIcon::fromTheme(name); + return QIcon(":/" + BuildConfig.LAUNCHER_SVGFILENAME); } bool Application::openJsonEditor(const QString& filename) diff --git a/launcher/Application.h b/launcher/Application.h index 52a84b461..0fd733b50 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -116,7 +116,7 @@ class Application : public QApplication { qint64 timeSinceStart() const { return m_startTime.msecsTo(QDateTime::currentDateTime()); } - QIcon getThemedIcon(const QString& name); + QIcon logo(); ThemeManager* themeManager() { return m_themeManager.get(); } diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 950b2276a..32048db8e 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -37,9 +37,9 @@ #include "VersionProxyModel.h" #include #include +#include #include #include -#include "Application.h" class VersionFilterModel : public QSortFilterProxyModel { Q_OBJECT @@ -206,11 +206,11 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const if (column == Name && hasRecommended) { auto recommenced = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); if (recommenced.toBool()) { - return APPLICATION->getThemedIcon("star"); + return QIcon::fromTheme("star"); } else if (hasLatest) { auto latest = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); if (latest.toBool()) { - return APPLICATION->getThemedIcon("bug"); + return QIcon::fromTheme("bug"); } } QPixmap pixmap; diff --git a/launcher/minecraft/ShortcutUtils.cpp b/launcher/minecraft/ShortcutUtils.cpp index 0336a9512..ec4ebb31a 100644 --- a/launcher/minecraft/ShortcutUtils.cpp +++ b/launcher/minecraft/ShortcutUtils.cpp @@ -123,7 +123,7 @@ bool createInstanceShortcut(const Shortcut& shortcut, const QString& filePath) // part of fix for weird bug involving the window icon being replaced // dunno why it happens, but parent 2-line fix seems to be enough, so w/e - auto appIcon = APPLICATION->getThemedIcon("logo"); + auto appIcon = APPLICATION->logo(); QFile iconFile(iconPath); if (!iconFile.open(QFile::WriteOnly)) { diff --git a/launcher/minecraft/mod/DataPackFolderModel.cpp b/launcher/minecraft/mod/DataPackFolderModel.cpp index 45cf1271f..1a2badd77 100644 --- a/launcher/minecraft/mod/DataPackFolderModel.cpp +++ b/launcher/minecraft/mod/DataPackFolderModel.cpp @@ -42,7 +42,6 @@ #include #include -#include "Application.h" #include "Version.h" #include "minecraft/mod/tasks/LocalDataPackParseTask.h" @@ -92,7 +91,7 @@ QVariant DataPackFolderModel::data(const QModelIndex& index, int role) const } case Qt::DecorationRole: { if (column == NameColumn && (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink())) - return APPLICATION->getThemedIcon("status-yellow"); + return QIcon::fromTheme("status-yellow"); if (column == ImageColumn) { return at(row).image({ 32, 32 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding); } diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index b613e0af1..45ec76f19 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -49,8 +49,6 @@ #include #include -#include "Application.h" - #include "minecraft/mod/tasks/LocalModParseTask.h" ModFolderModel::ModFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent) @@ -132,7 +130,7 @@ QVariant ModFolderModel::data(const QModelIndex& index, int role) const return m_resources[row]->internal_id(); case Qt::DecorationRole: { if (column == NameColumn && (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink())) - return APPLICATION->getThemedIcon("status-yellow"); + return QIcon::fromTheme("status-yellow"); if (column == ImageColumn) { return at(row).icon({ 32, 32 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding); } diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index f93002f06..2b4f9eb14 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -503,7 +503,7 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const return m_resources[row]->internal_id(); case Qt::DecorationRole: { if (column == NameColumn && (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink())) - return APPLICATION->getThemedIcon("status-yellow"); + return QIcon::fromTheme("status-yellow"); return {}; } @@ -709,8 +709,7 @@ SortType ResourceFolderModel::columnToSortKey(size_t column) const } /* Standard Proxy Model for createFilterProxyModel */ -bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, - [[maybe_unused]] const QModelIndex& source_parent) const +bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, [[maybe_unused]] const QModelIndex& source_parent) const { auto* model = qobject_cast(sourceModel()); if (!model) diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index d9f27a043..df572484b 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -41,7 +41,6 @@ #include #include -#include "Application.h" #include "Version.h" #include "minecraft/mod/tasks/LocalDataPackParseTask.h" @@ -96,7 +95,7 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const } case Qt::DecorationRole: { if (column == NameColumn && (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink())) - return APPLICATION->getThemedIcon("status-yellow"); + return QIcon::fromTheme("status-yellow"); if (column == ImageColumn) { return at(row).image({ 32, 32 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding); } diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 8b89b45cd..57c5f8ee9 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -33,10 +33,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include - -#include "Application.h" - #include "TexturePackFolderModel.h" #include "minecraft/mod/tasks/LocalTexturePackParseTask.h" @@ -98,7 +94,7 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const return m_resources[row]->internal_id(); case Qt::DecorationRole: { if (column == NameColumn && (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink())) - return APPLICATION->getThemedIcon("status-yellow"); + return QIcon::fromTheme("status-yellow"); if (column == ImageColumn) { return at(row).image({ 32, 32 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding); } diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index d89224504..3cec0ae53 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -148,7 +148,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi { ui->setupUi(this); - setWindowIcon(APPLICATION->getThemedIcon("logo")); + setWindowIcon(APPLICATION->logo()); setWindowTitle(APPLICATION->applicationDisplayName()); #ifndef QT_NO_ACCESSIBILITY setAccessibleName(BuildConfig.LAUNCHER_DISPLAYNAME); @@ -165,7 +165,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi // qt designer will delete it when you save the file >:( changeIconButton = new LabeledToolButton(this); changeIconButton->setObjectName(QStringLiteral("changeIconButton")); - changeIconButton->setIcon(APPLICATION->getThemedIcon("news")); + changeIconButton->setIcon(QIcon::fromTheme("news")); changeIconButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); connect(changeIconButton, &QToolButton::clicked, this, &MainWindow::on_actionChangeInstIcon_triggered); ui->instanceToolBar->insertWidgetBefore(ui->actionLaunchInstance, changeIconButton); @@ -277,7 +277,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi { m_newsChecker.reset(new NewsChecker(APPLICATION->network(), BuildConfig.NEWS_RSS_URL)); newsLabel = new QToolButton(); - newsLabel->setIcon(APPLICATION->getThemedIcon("news")); + newsLabel->setIcon(QIcon::fromTheme("news")); newsLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); newsLabel->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); newsLabel->setFocusPolicy(Qt::NoFocus); @@ -684,7 +684,7 @@ void MainWindow::repopulateAccountsMenu() if (!face.isNull()) { action->setIcon(face); } else { - action->setIcon(APPLICATION->getThemedIcon("noaccount")); + action->setIcon(QIcon::fromTheme("noaccount")); } const int highestNumberKey = 9; @@ -755,7 +755,7 @@ void MainWindow::defaultAccountChanged() ui->actionAccountsButton->setText(profileLabel); auto face = account->getFace(); if (face.isNull()) { - ui->actionAccountsButton->setIcon(APPLICATION->getThemedIcon("noaccount")); + ui->actionAccountsButton->setIcon(QIcon::fromTheme("noaccount")); } else { ui->actionAccountsButton->setIcon(face); } @@ -763,7 +763,7 @@ void MainWindow::defaultAccountChanged() } // Set the icon to the "no account" icon. - ui->actionAccountsButton->setIcon(APPLICATION->getThemedIcon("noaccount")); + ui->actionAccountsButton->setIcon(QIcon::fromTheme("noaccount")); ui->actionAccountsButton->setText(tr("Accounts")); } diff --git a/launcher/ui/ViewLogWindow.cpp b/launcher/ui/ViewLogWindow.cpp index c0c56f3ee..f4390e2f1 100644 --- a/launcher/ui/ViewLogWindow.cpp +++ b/launcher/ui/ViewLogWindow.cpp @@ -8,7 +8,7 @@ ViewLogWindow::ViewLogWindow(QWidget* parent) : QMainWindow(parent), m_page(new OtherLogsPage("launcher-logs", tr("Launcher Logs"), "Launcher-Logs", nullptr, parent)) { setAttribute(Qt::WA_DeleteOnClose); - setWindowIcon(APPLICATION->getThemedIcon("log")); + setWindowIcon(QIcon::fromTheme("log")); setWindowTitle(tr("View Launcher Logs")); setCentralWidget(m_page); setMinimumSize(m_page->size()); diff --git a/launcher/ui/dialogs/AboutDialog.cpp b/launcher/ui/dialogs/AboutDialog.cpp index 5b7d44ff7..0f3067719 100644 --- a/launcher/ui/dialogs/AboutDialog.cpp +++ b/launcher/ui/dialogs/AboutDialog.cpp @@ -147,7 +147,7 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDia ui->urlLabel->setOpenExternalLinks(true); - ui->icon->setPixmap(APPLICATION->getThemedIcon("logo").pixmap(64)); + ui->icon->setPixmap(APPLICATION->logo().pixmap(64)); ui->title->setText(launcherName); ui->versionLabel->setText(BuildConfig.printableVersionString()); diff --git a/launcher/ui/dialogs/CreateShortcutDialog.cpp b/launcher/ui/dialogs/CreateShortcutDialog.cpp index 5cfe33c7f..574881ad0 100644 --- a/launcher/ui/dialogs/CreateShortcutDialog.cpp +++ b/launcher/ui/dialogs/CreateShortcutDialog.cpp @@ -38,7 +38,6 @@ #include #include -#include "Application.h" #include "BuildConfig.h" #include "CreateShortcutDialog.h" #include "ui_CreateShortcutDialog.h" @@ -112,7 +111,7 @@ CreateShortcutDialog::CreateShortcutDialog(InstancePtr instance, QWidget* parent if (account->isInUse()) profileLabel = tr("%1 (in use)").arg(profileLabel); auto face = account->getFace(); - QIcon icon = face.isNull() ? APPLICATION->getThemedIcon("noaccount") : face; + QIcon icon = face.isNull() ? QIcon::fromTheme("noaccount") : face; ui->accountSelectionBox->addItem(profileLabel, account->profileName()); ui->accountSelectionBox->setItemIcon(i, icon); if (defaultAccount == account) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 7082125f2..552b83776 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -53,7 +53,7 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { QString id() const override { return uid; } QString displayName() const override { return name; } - QIcon icon() const override { return APPLICATION->getThemedIcon(iconName); } + QIcon icon() const override { return QIcon::fromTheme(iconName); } void openedImpl() override { diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index 9e74cd7ac..5542f6986 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -74,7 +74,7 @@ NewInstanceDialog::NewInstanceDialog(const QString& initialGroup, { ui->setupUi(this); - setWindowIcon(APPLICATION->getThemedIcon("new")); + setWindowIcon(QIcon::fromTheme("new")); InstIconKey = "default"; ui->iconButton->setIcon(APPLICATION->icons()->getIcon(InstIconKey)); diff --git a/launcher/ui/dialogs/ProfileSetupDialog.cpp b/launcher/ui/dialogs/ProfileSetupDialog.cpp index 0b5e1a784..af8b26c66 100644 --- a/launcher/ui/dialogs/ProfileSetupDialog.cpp +++ b/launcher/ui/dialogs/ProfileSetupDialog.cpp @@ -55,9 +55,9 @@ ProfileSetupDialog::ProfileSetupDialog(MinecraftAccountPtr accountToSetup, QWidg ui->setupUi(this); ui->errorLabel->setVisible(false); - goodIcon = APPLICATION->getThemedIcon("status-good"); - yellowIcon = APPLICATION->getThemedIcon("status-yellow"); - badIcon = APPLICATION->getThemedIcon("status-bad"); + goodIcon = QIcon::fromTheme("status-good"); + yellowIcon = QIcon::fromTheme("status-yellow"); + badIcon = QIcon::fromTheme("status-bad"); static const QRegularExpression s_permittedNames("[a-zA-Z0-9_]{3,16}"); auto nameEdit = ui->nameEdit; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 191feeb88..3015ae6e7 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -59,7 +59,7 @@ ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, const std::share resize(static_cast(std::max(0.5 * parent->width(), 400.0)), static_cast(std::max(0.75 * parent->height(), 400.0))); - setWindowIcon(APPLICATION->getThemedIcon("new")); + setWindowIcon(QIcon::fromTheme("new")); // Bonk Qt over its stupid head and make sure it understands which button is the default one... // See: https://stackoverflow.com/questions/24556831/qbuttonbox-set-default-button diff --git a/launcher/ui/dialogs/ReviewMessageBox.cpp b/launcher/ui/dialogs/ReviewMessageBox.cpp index 96cc8149f..c5f7b5fbe 100644 --- a/launcher/ui/dialogs/ReviewMessageBox.cpp +++ b/launcher/ui/dialogs/ReviewMessageBox.cpp @@ -1,8 +1,6 @@ #include "ReviewMessageBox.h" #include "ui_ReviewMessageBox.h" -#include "Application.h" - #include ReviewMessageBox::ReviewMessageBox(QWidget* parent, [[maybe_unused]] QString const& title, [[maybe_unused]] QString const& icon) @@ -56,7 +54,7 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info) itemTop->insertChildren(1, { customPathItem }); - itemTop->setIcon(1, QIcon(APPLICATION->getThemedIcon("status-yellow"))); + itemTop->setIcon(1, QIcon(QIcon::fromTheme("status-yellow"))); itemTop->setToolTip( childIndx++, tr("This file will be downloaded to a folder location different from the default, possibly due to its loader requiring it.")); diff --git a/launcher/ui/dialogs/UpdateAvailableDialog.cpp b/launcher/ui/dialogs/UpdateAvailableDialog.cpp index 810a1f089..f288fe760 100644 --- a/launcher/ui/dialogs/UpdateAvailableDialog.cpp +++ b/launcher/ui/dialogs/UpdateAvailableDialog.cpp @@ -22,7 +22,6 @@ #include "UpdateAvailableDialog.h" #include -#include "Application.h" #include "BuildConfig.h" #include "Markdown.h" #include "StringUtils.h" @@ -41,7 +40,7 @@ UpdateAvailableDialog::UpdateAvailableDialog(const QString& currentVersion, ui->headerLabel->setText(tr("A new version of %1 is available!").arg(launcherName)); ui->versionAvailableLabel->setText( tr("Version %1 is now available - you have %2 . Would you like to download it now?").arg(availableVersion).arg(currentVersion)); - ui->icon->setPixmap(APPLICATION->getThemedIcon("checkupdate").pixmap(64)); + ui->icon->setPixmap(QIcon::fromTheme("checkupdate").pixmap(64)); auto releaseNotesHtml = markdownToHTML(releaseNotes); ui->releaseNotes->setHtml(StringUtils::htmlListPatch(releaseNotesHtml)); diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index 4a628b003..1db4971f4 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -97,7 +97,7 @@ class InstallJavaPage : public QWidget, public BasePage { QString id() const override { return uid; } QString displayName() const override { return name; } - QIcon icon() const override { return APPLICATION->getThemedIcon(iconName); } + QIcon icon() const override { return QIcon::fromTheme(iconName); } void openedImpl() override { diff --git a/launcher/ui/pages/global/APIPage.h b/launcher/ui/pages/global/APIPage.h index 9252a9ab3..7a22aa069 100644 --- a/launcher/ui/pages/global/APIPage.h +++ b/launcher/ui/pages/global/APIPage.h @@ -39,7 +39,6 @@ #include -#include #include "ui/pages/BasePage.h" namespace Ui { @@ -54,7 +53,7 @@ class APIPage : public QWidget, public BasePage { ~APIPage(); QString displayName() const override { return tr("Services"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("worlds"); } + QIcon icon() const override { return QIcon::fromTheme("worlds"); } QString id() const override { return "apis"; } QString helpPage() const override { return "APIs"; } virtual bool apply() override; diff --git a/launcher/ui/pages/global/AccountListPage.h b/launcher/ui/pages/global/AccountListPage.h index 7bd5101c0..2841b9456 100644 --- a/launcher/ui/pages/global/AccountListPage.h +++ b/launcher/ui/pages/global/AccountListPage.h @@ -41,7 +41,6 @@ #include "ui/pages/BasePage.h" -#include "Application.h" #include "minecraft/auth/AccountList.h" namespace Ui { @@ -59,9 +58,9 @@ class AccountListPage : public QMainWindow, public BasePage { QString displayName() const override { return tr("Accounts"); } QIcon icon() const override { - auto icon = APPLICATION->getThemedIcon("accounts"); + auto icon = QIcon::fromTheme("accounts"); if (icon.isNull()) { - icon = APPLICATION->getThemedIcon("noaccount"); + icon = QIcon::fromTheme("noaccount"); } return icon; } diff --git a/launcher/ui/pages/global/AppearancePage.h b/launcher/ui/pages/global/AppearancePage.h index 29b2d34bf..2220db2cd 100644 --- a/launcher/ui/pages/global/AppearancePage.h +++ b/launcher/ui/pages/global/AppearancePage.h @@ -37,7 +37,6 @@ #include #include -#include "Application.h" #include "java/JavaChecker.h" #include "translations/TranslationsModel.h" #include "ui/pages/BasePage.h" @@ -53,7 +52,7 @@ class AppearancePage : public AppearanceWidget, public BasePage { explicit AppearancePage(QWidget* parent = nullptr) : AppearanceWidget(false, parent) { layout()->setContentsMargins(0, 0, 6, 0); } QString displayName() const override { return tr("Appearance"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("appearance"); } + QIcon icon() const override { return QIcon::fromTheme("appearance"); } QString id() const override { return "appearance-settings"; } QString helpPage() const override { return "Launcher-settings"; } diff --git a/launcher/ui/pages/global/ExternalToolsPage.h b/launcher/ui/pages/global/ExternalToolsPage.h index 377488ccf..702ace557 100644 --- a/launcher/ui/pages/global/ExternalToolsPage.h +++ b/launcher/ui/pages/global/ExternalToolsPage.h @@ -37,7 +37,6 @@ #include -#include #include "ui/pages/BasePage.h" namespace Ui { @@ -54,9 +53,9 @@ class ExternalToolsPage : public QWidget, public BasePage { QString displayName() const override { return tr("Tools"); } QIcon icon() const override { - auto icon = APPLICATION->getThemedIcon("externaltools"); + auto icon = QIcon::fromTheme("externaltools"); if (icon.isNull()) { - icon = APPLICATION->getThemedIcon("loadermods"); + icon = QIcon::fromTheme("loadermods"); } return icon; } diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h index b30fa22e3..79a3d1b96 100644 --- a/launcher/ui/pages/global/JavaPage.h +++ b/launcher/ui/pages/global/JavaPage.h @@ -35,7 +35,6 @@ #pragma once -#include #include #include #include @@ -57,7 +56,7 @@ class JavaPage : public QWidget, public BasePage { ~JavaPage(); QString displayName() const override { return tr("Java"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("java"); } + QIcon icon() const override { return QIcon::fromTheme("java"); } QString id() const override { return "java-settings"; } QString helpPage() const override { return "Java-settings"; } void retranslate() override; diff --git a/launcher/ui/pages/global/LanguagePage.cpp b/launcher/ui/pages/global/LanguagePage.cpp index af6fc1727..f4be75782 100644 --- a/launcher/ui/pages/global/LanguagePage.cpp +++ b/launcher/ui/pages/global/LanguagePage.cpp @@ -37,6 +37,7 @@ #include "LanguagePage.h" #include +#include "Application.h" #include "ui/widgets/LanguageSelectionWidget.h" LanguagePage::LanguagePage(QWidget* parent) : QWidget(parent) diff --git a/launcher/ui/pages/global/LanguagePage.h b/launcher/ui/pages/global/LanguagePage.h index ff7ce7ddc..b376e1cf2 100644 --- a/launcher/ui/pages/global/LanguagePage.h +++ b/launcher/ui/pages/global/LanguagePage.h @@ -36,7 +36,6 @@ #pragma once -#include #include #include #include "ui/pages/BasePage.h" @@ -51,7 +50,7 @@ class LanguagePage : public QWidget, public BasePage { virtual ~LanguagePage(); QString displayName() const override { return tr("Language"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("language"); } + QIcon icon() const override { return QIcon::fromTheme("language"); } QString id() const override { return "language-settings"; } QString helpPage() const override { return "Language-settings"; } bool apply() override; diff --git a/launcher/ui/pages/global/LauncherPage.h b/launcher/ui/pages/global/LauncherPage.h index d76c84b63..263bf08bb 100644 --- a/launcher/ui/pages/global/LauncherPage.h +++ b/launcher/ui/pages/global/LauncherPage.h @@ -38,7 +38,6 @@ #include #include -#include #include #include "java/JavaChecker.h" #include "ui/pages/BasePage.h" @@ -58,7 +57,7 @@ class LauncherPage : public QWidget, public BasePage { ~LauncherPage(); QString displayName() const override { return tr("General"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("settings"); } + QIcon icon() const override { return QIcon::fromTheme("settings"); } QString id() const override { return "launcher-settings"; } QString helpPage() const override { return "Launcher-settings"; } bool apply() override; diff --git a/launcher/ui/pages/global/MinecraftPage.h b/launcher/ui/pages/global/MinecraftPage.h index b21862536..c21d59a6b 100644 --- a/launcher/ui/pages/global/MinecraftPage.h +++ b/launcher/ui/pages/global/MinecraftPage.h @@ -38,7 +38,6 @@ #include #include -#include "Application.h" #include "java/JavaChecker.h" #include "ui/pages/BasePage.h" #include "ui/widgets/MinecraftSettingsWidget.h" @@ -53,7 +52,7 @@ class MinecraftPage : public MinecraftSettingsWidget, public BasePage { ~MinecraftPage() override {} QString displayName() const override { return tr("Minecraft"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("minecraft"); } + QIcon icon() const override { return QIcon::fromTheme("minecraft"); } QString id() const override { return "minecraft-settings"; } QString helpPage() const override { return "Minecraft-settings"; } bool apply() override diff --git a/launcher/ui/pages/global/ProxyPage.h b/launcher/ui/pages/global/ProxyPage.h index 26118f181..8689a5c80 100644 --- a/launcher/ui/pages/global/ProxyPage.h +++ b/launcher/ui/pages/global/ProxyPage.h @@ -40,7 +40,6 @@ #include #include -#include #include "ui/pages/BasePage.h" namespace Ui { @@ -55,7 +54,7 @@ class ProxyPage : public QWidget, public BasePage { ~ProxyPage(); QString displayName() const override { return tr("Proxy"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("proxy"); } + QIcon icon() const override { return QIcon::fromTheme("proxy"); } QString id() const override { return "proxy-settings"; } QString helpPage() const override { return "Proxy-settings"; } bool apply() override; diff --git a/launcher/ui/pages/instance/DataPackPage.h b/launcher/ui/pages/instance/DataPackPage.h index b71ed2965..bed84540a 100644 --- a/launcher/ui/pages/instance/DataPackPage.h +++ b/launcher/ui/pages/instance/DataPackPage.h @@ -29,7 +29,7 @@ class DataPackPage : public ExternalResourcesPage { explicit DataPackPage(BaseInstance* instance, std::shared_ptr model, QWidget* parent = nullptr); QString displayName() const override { return QObject::tr("Data Packs"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("datapacks"); } + QIcon icon() const override { return QIcon::fromTheme("datapacks"); } QString id() const override { return "datapacks"; } QString helpPage() const override { return "Data-packs"; } bool shouldDisplay() const override { return true; } diff --git a/launcher/ui/pages/instance/GameOptionsPage.h b/launcher/ui/pages/instance/GameOptionsPage.h index a132843e7..43f91976c 100644 --- a/launcher/ui/pages/instance/GameOptionsPage.h +++ b/launcher/ui/pages/instance/GameOptionsPage.h @@ -38,7 +38,6 @@ #include #include -#include #include "ui/pages/BasePage.h" namespace Ui { @@ -59,7 +58,7 @@ class GameOptionsPage : public QWidget, public BasePage { void closedImpl() override; virtual QString displayName() const override { return tr("Game Options"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("settings"); } + virtual QIcon icon() const override { return QIcon::fromTheme("settings"); } virtual QString id() const override { return "gameoptions"; } virtual QString helpPage() const override { return "Game-Options-management"; } void retranslate() override; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 2c507e84b..aca47e2c7 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -36,7 +36,6 @@ #pragma once #include -#include "Application.h" #include "BaseInstance.h" #include "ui/pages/BasePage.h" #include "ui/widgets/MinecraftSettingsWidget.h" @@ -53,7 +52,7 @@ class InstanceSettingsPage : public MinecraftSettingsWidget, public BasePage { } ~InstanceSettingsPage() override {} QString displayName() const override { return tr("Settings"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("instance-settings"); } + QIcon icon() const override { return QIcon::fromTheme("instance-settings"); } QString id() const override { return "settings"; } bool apply() override { diff --git a/launcher/ui/pages/instance/LogPage.h b/launcher/ui/pages/instance/LogPage.h index b4d74fb9c..636a8b70d 100644 --- a/launcher/ui/pages/instance/LogPage.h +++ b/launcher/ui/pages/instance/LogPage.h @@ -38,7 +38,6 @@ #include #include -#include #include "BaseInstance.h" #include "launch/LaunchTask.h" #include "ui/pages/BasePage.h" @@ -67,7 +66,7 @@ class LogPage : public QWidget, public BasePage { explicit LogPage(InstancePtr instance, QWidget* parent = 0); virtual ~LogPage(); virtual QString displayName() const override { return tr("Minecraft Log"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("log"); } + virtual QIcon icon() const override { return QIcon::fromTheme("log"); } virtual QString id() const override { return "console"; } virtual bool apply() override; virtual QString helpPage() const override { return "Minecraft-Logs"; } diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index d46f0f8d5..e97935650 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -166,7 +166,7 @@ QString ManagedPackPage::displayName() const QIcon ManagedPackPage::icon() const { - return APPLICATION->getThemedIcon(m_inst->getManagedPackType()); + return QIcon::fromTheme(m_inst->getManagedPackType()); } QString ManagedPackPage::helpPage() const diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index 9b9665571..b33992470 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -52,7 +52,7 @@ class ModFolderPage : public ExternalResourcesPage { void setFilter(const QString& filter) { m_fileSelectionFilter = filter; } virtual QString displayName() const override { return tr("Mods"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("loadermods"); } + virtual QIcon icon() const override { return QIcon::fromTheme("loadermods"); } virtual QString id() const override { return "mods"; } virtual QString helpPage() const override { return "Loader-mods"; } @@ -83,7 +83,7 @@ class CoreModFolderPage : public ModFolderPage { virtual ~CoreModFolderPage() = default; virtual QString displayName() const override { return tr("Core Mods"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("coremods"); } + virtual QIcon icon() const override { return QIcon::fromTheme("coremods"); } virtual QString id() const override { return "coremods"; } virtual QString helpPage() const override { return "Core-mods"; } @@ -97,7 +97,7 @@ class NilModFolderPage : public ModFolderPage { virtual ~NilModFolderPage() = default; virtual QString displayName() const override { return tr("Nilmods"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("coremods"); } + virtual QIcon icon() const override { return QIcon::fromTheme("coremods"); } virtual QString id() const override { return "nilmods"; } virtual QString helpPage() const override { return "Nilmods"; } diff --git a/launcher/ui/pages/instance/NotesPage.h b/launcher/ui/pages/instance/NotesPage.h index 3351d25fc..f11e2ad7c 100644 --- a/launcher/ui/pages/instance/NotesPage.h +++ b/launcher/ui/pages/instance/NotesPage.h @@ -37,7 +37,6 @@ #include -#include #include "BaseInstance.h" #include "ui/pages/BasePage.h" @@ -54,9 +53,9 @@ class NotesPage : public QWidget, public BasePage { virtual QString displayName() const override { return tr("Notes"); } virtual QIcon icon() const override { - auto icon = APPLICATION->getThemedIcon("notes"); + auto icon = QIcon::fromTheme("notes"); if (icon.isNull()) - icon = APPLICATION->getThemedIcon("news"); + icon = QIcon::fromTheme("news"); return icon; } virtual QString id() const override { return "notes"; } diff --git a/launcher/ui/pages/instance/OtherLogsPage.h b/launcher/ui/pages/instance/OtherLogsPage.h index fbf9991e1..9fc0ba3b9 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.h +++ b/launcher/ui/pages/instance/OtherLogsPage.h @@ -57,7 +57,7 @@ class OtherLogsPage : public QWidget, public BasePage { QString id() const override { return m_id; } QString displayName() const override { return m_displayName; } - QIcon icon() const override { return APPLICATION->getThemedIcon("log"); } + QIcon icon() const override { return QIcon::fromTheme("log"); } QString helpPage() const override { return m_helpPage; } void retranslate() override; diff --git a/launcher/ui/pages/instance/ResourcePackPage.h b/launcher/ui/pages/instance/ResourcePackPage.h index 40fe10b79..0ad24fc45 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.h +++ b/launcher/ui/pages/instance/ResourcePackPage.h @@ -51,7 +51,7 @@ class ResourcePackPage : public ExternalResourcesPage { explicit ResourcePackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent = 0); QString displayName() const override { return tr("Resource Packs"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("resourcepacks"); } + QIcon icon() const override { return QIcon::fromTheme("resourcepacks"); } QString id() const override { return "resourcepacks"; } QString helpPage() const override { return "Resource-packs"; } diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index 082b44308..9aa7ea50a 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -134,7 +134,7 @@ class FilterModel : public QIdentityProxyModel { { m_thumbnailingPool.setMaxThreadCount(4); m_thumbnailCache = std::make_shared(); - m_thumbnailCache->add("placeholder", APPLICATION->getThemedIcon("screenshot-placeholder")); + m_thumbnailCache->add("placeholder", QIcon::fromTheme("screenshot-placeholder")); connect(&watcher, &QFileSystemWatcher::fileChanged, this, &FilterModel::fileChanged); } virtual ~FilterModel() diff --git a/launcher/ui/pages/instance/ScreenshotsPage.h b/launcher/ui/pages/instance/ScreenshotsPage.h index bb127b429..b9c750a1f 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.h +++ b/launcher/ui/pages/instance/ScreenshotsPage.h @@ -37,7 +37,6 @@ #include -#include #include "ui/pages/BasePage.h" #include "settings/Setting.h" @@ -67,7 +66,7 @@ class ScreenshotsPage : public QMainWindow, public BasePage { virtual bool eventFilter(QObject*, QEvent*) override; virtual QString displayName() const override { return tr("Screenshots"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("screenshots"); } + virtual QIcon icon() const override { return QIcon::fromTheme("screenshots"); } virtual QString id() const override { return "screenshots"; } virtual QString helpPage() const override { return "Screenshots-management"; } virtual bool apply() override { return !m_uploadActive; } diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index d1f39bb88..f616a5b22 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -36,6 +36,7 @@ */ #include "ServersPage.h" +#include "Application.h" #include "ServerPingTask.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui_ServersPage.h" @@ -319,7 +320,7 @@ class ServersModel : public QAbstractListModel { if (px.loadFromData(bytes)) return QIcon(px); } - return APPLICATION->getThemedIcon("unknown_server"); + return QIcon::fromTheme("unknown_server"); } case 1: return m_servers[row].m_address; diff --git a/launcher/ui/pages/instance/ServersPage.h b/launcher/ui/pages/instance/ServersPage.h index 77710d6cc..49a746245 100644 --- a/launcher/ui/pages/instance/ServersPage.h +++ b/launcher/ui/pages/instance/ServersPage.h @@ -39,7 +39,7 @@ #include #include -#include +#include "BaseInstance.h" #include "ui/pages/BasePage.h" #include "settings/Setting.h" @@ -63,7 +63,7 @@ class ServersPage : public QMainWindow, public BasePage { void closedImpl() override; virtual QString displayName() const override { return tr("Servers"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("server"); } + virtual QIcon icon() const override { return QIcon::fromTheme("server"); } virtual QString id() const override { return "servers"; } virtual QString helpPage() const override { return "Servers-management"; } void retranslate() override; diff --git a/launcher/ui/pages/instance/ShaderPackPage.h b/launcher/ui/pages/instance/ShaderPackPage.h index 128c48ae7..c6ae3bc24 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.h +++ b/launcher/ui/pages/instance/ShaderPackPage.h @@ -48,7 +48,7 @@ class ShaderPackPage : public ExternalResourcesPage { ~ShaderPackPage() override = default; QString displayName() const override { return tr("Shader Packs"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("shaderpacks"); } + QIcon icon() const override { return QIcon::fromTheme("shaderpacks"); } QString id() const override { return "shaderpacks"; } QString helpPage() const override { return "shader-packs"; } diff --git a/launcher/ui/pages/instance/TexturePackPage.h b/launcher/ui/pages/instance/TexturePackPage.h index 3ebca3e87..2c92212b9 100644 --- a/launcher/ui/pages/instance/TexturePackPage.h +++ b/launcher/ui/pages/instance/TexturePackPage.h @@ -51,7 +51,7 @@ class TexturePackPage : public ExternalResourcesPage { explicit TexturePackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent = nullptr); QString displayName() const override { return tr("Texture packs"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("resourcepacks"); } + QIcon icon() const override { return QIcon::fromTheme("resourcepacks"); } QString id() const override { return "texturepacks"; } QString helpPage() const override { return "Texture-packs"; } diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index d355f38fb..ef5427a00 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -91,12 +91,12 @@ class IconProxy : public QIdentityProxyModel { if (!var.isNull()) { auto string = var.toString(); if (string == "warning") { - return APPLICATION->getThemedIcon("status-yellow"); + return QIcon::fromTheme("status-yellow"); } else if (string == "error") { - return APPLICATION->getThemedIcon("status-bad"); + return QIcon::fromTheme("status-bad"); } } - return APPLICATION->getThemedIcon("status-good"); + return QIcon::fromTheme("status-good"); } return var; } diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index 31f3bfd3e..c7eaf94a0 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -48,10 +48,10 @@ #include #include #include +#include #include #include #include -#include #include "FileSystem.h" #include "tools/MCEditTool.h" @@ -77,7 +77,7 @@ class WorldListProxyModel : public QSortFilterProxyModel { auto iconFile = worlds->data(sourceIndex, WorldList::IconFileRole).toString(); if (iconFile.isNull()) { // NOTE: Minecraft uses the same placeholder for servers AND worlds - return APPLICATION->getThemedIcon("unknown_server"); + return QIcon::fromTheme("unknown_server"); } return QIcon(iconFile); } diff --git a/launcher/ui/pages/instance/WorldListPage.h b/launcher/ui/pages/instance/WorldListPage.h index 08cf7dc5f..9b931066d 100644 --- a/launcher/ui/pages/instance/WorldListPage.h +++ b/launcher/ui/pages/instance/WorldListPage.h @@ -37,7 +37,6 @@ #include -#include #include #include "minecraft/MinecraftInstance.h" #include "ui/pages/BasePage.h" @@ -57,7 +56,7 @@ class WorldListPage : public QMainWindow, public BasePage { virtual ~WorldListPage(); virtual QString displayName() const override { return tr("Worlds"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("worlds"); } + virtual QIcon icon() const override { return QIcon::fromTheme("worlds"); } virtual QString id() const override { return "worlds"; } virtual QString helpPage() const override { return "Worlds"; } virtual bool shouldDisplay() const override; diff --git a/launcher/ui/pages/modplatform/CustomPage.h b/launcher/ui/pages/modplatform/CustomPage.h index c5d6d5af5..2bfb1de29 100644 --- a/launcher/ui/pages/modplatform/CustomPage.h +++ b/launcher/ui/pages/modplatform/CustomPage.h @@ -37,7 +37,7 @@ #include -#include +#include "BaseVersion.h" #include "tasks/Task.h" #include "ui/pages/BasePage.h" @@ -54,7 +54,7 @@ class CustomPage : public QWidget, public BasePage { explicit CustomPage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~CustomPage(); virtual QString displayName() const override { return tr("Custom"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("minecraft"); } + virtual QIcon icon() const override { return QIcon::fromTheme("minecraft"); } virtual QString id() const override { return "vanilla"; } virtual QString helpPage() const override { return "Vanilla-platform"; } virtual bool shouldDisplay() const override; diff --git a/launcher/ui/pages/modplatform/ImportPage.h b/launcher/ui/pages/modplatform/ImportPage.h index 70d7736eb..1119e709a 100644 --- a/launcher/ui/pages/modplatform/ImportPage.h +++ b/launcher/ui/pages/modplatform/ImportPage.h @@ -37,7 +37,6 @@ #include -#include #include "tasks/Task.h" #include "ui/pages/BasePage.h" @@ -54,7 +53,7 @@ class ImportPage : public QWidget, public BasePage { explicit ImportPage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~ImportPage(); virtual QString displayName() const override { return tr("Import"); } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("viewfolder"); } + virtual QIcon icon() const override { return QIcon::fromTheme("viewfolder"); } virtual QString id() const override { return "import"; } virtual QString helpPage() const override { return "Zip-import"; } virtual bool shouldDisplay() const override; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 5ea70789e..eea7af25e 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -65,7 +65,7 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant icon_or_none.has_value()) return icon_or_none.value(); - return APPLICATION->getThemedIcon("screenshot-placeholder"); + return QIcon::fromTheme("screenshot-placeholder"); } else { return {}; } diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index 9e2e7a2ca..c5fec48d7 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -61,7 +61,7 @@ QVariant ListModel::data(const QModelIndex& index, int role) const if (m_logoMap.contains(pack.safeName)) { return (m_logoMap.value(pack.safeName)); } - auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder"); + auto icon = QIcon::fromTheme("atlauncher-placeholder"); auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1").arg(pack.safeName); ((ListModel*)this)->requestLogo(pack.safeName, url); diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.h b/launcher/ui/pages/modplatform/atlauncher/AtlPage.h index 556e90b1d..8c8bf53b3 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.h @@ -41,7 +41,6 @@ #include #include -#include "Application.h" #include "ui/pages/modplatform/ModpackProviderBasePage.h" namespace Ui { @@ -57,7 +56,7 @@ class AtlPage : public QWidget, public ModpackProviderBasePage { explicit AtlPage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~AtlPage(); virtual QString displayName() const override { return "ATLauncher"; } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("atlauncher"); } + virtual QIcon icon() const override { return QIcon::fromTheme("atlauncher"); } virtual QString id() const override { return "atl"; } virtual QString helpPage() const override { return "ATL-platform"; } virtual bool shouldDisplay() const override; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index ea051bd39..e5d880dca 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -50,7 +50,7 @@ QVariant ListModel::data(const QModelIndex& index, int role) const if (m_logoMap.contains(pack->logoName)) { return (m_logoMap.value(pack->logoName)); } - QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); + QIcon icon = QIcon::fromTheme("screenshot-placeholder"); ((ListModel*)this)->requestLogo(pack->logoName, pack->logoUrl); return icon; } diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index 2252efa07..eb763229f 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -37,7 +37,6 @@ #include -#include #include #include "modplatform/ModIndex.h" #include "ui/pages/modplatform/ModpackProviderBasePage.h" @@ -61,7 +60,7 @@ class FlamePage : public QWidget, public ModpackProviderBasePage { explicit FlamePage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~FlamePage(); virtual QString displayName() const override { return "CurseForge"; } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("flame"); } + virtual QIcon icon() const override { return QIcon::fromTheme("flame"); } virtual QString id() const override { return "flame"; } virtual QString helpPage() const override { return "Flame-platform"; } virtual bool shouldDisplay() const override; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index 19f3731c7..d4b697ae0 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -40,7 +40,6 @@ #pragma once #include -#include "Application.h" #include "modplatform/ResourceAPI.h" @@ -58,7 +57,7 @@ static inline QString displayName() } static inline QIcon icon() { - return APPLICATION->getThemedIcon("flame"); + return QIcon::fromTheme("flame"); } static inline QString id() { @@ -181,8 +180,6 @@ class FlameShaderPackPage : public ShaderPackResourcePage { void openUrl(const QUrl& url) override; }; - - class FlameDataPackPage : public DataPackResourcePage { Q_OBJECT diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h index c00a93dfa..25b900f97 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h @@ -23,7 +23,6 @@ #include #include -#include #include "modplatform/import_ftb/PackHelpers.h" #include "ui/pages/modplatform/ModpackProviderBasePage.h" #include "ui/pages/modplatform/import_ftb/ListModel.h" @@ -42,7 +41,7 @@ class ImportFTBPage : public QWidget, public ModpackProviderBasePage { explicit ImportFTBPage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~ImportFTBPage(); QString displayName() const override { return tr("FTB App Import"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("ftb_logo"); } + QIcon icon() const override { return QIcon::fromTheme("ftb_logo"); } QString id() const override { return "import_ftb"; } QString helpPage() const override { return "FTB-import"; } bool shouldDisplay() const override { return true; } diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index efa9bd3bc..eb95b291c 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -173,7 +173,7 @@ QVariant ListModel::data(const QModelIndex& index, int role) const if (m_logoMap.contains(pack.logo)) { return (m_logoMap.value(pack.logo)); } - QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); + QIcon icon = QIcon::fromTheme("screenshot-placeholder"); ((ListModel*)this)->requestLogo(pack.logo); return icon; } diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.h b/launcher/ui/pages/modplatform/legacy_ftb/Page.h index fc789971f..db70ae79e 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.h @@ -39,7 +39,6 @@ #include #include -#include #include "QObjectPtr.h" #include "modplatform/legacy_ftb/PackFetchTask.h" #include "modplatform/legacy_ftb/PackHelpers.h" @@ -64,7 +63,7 @@ class Page : public QWidget, public ModpackProviderBasePage { explicit Page(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~Page(); QString displayName() const override { return "FTB Legacy"; } - QIcon icon() const override { return APPLICATION->getThemedIcon("ftb_logo"); } + QIcon icon() const override { return QIcon::fromTheme("ftb_logo"); } QString id() const override { return "legacy_ftb"; } QString helpPage() const override { return "FTB-legacy"; } bool shouldDisplay() const override; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index bf6215356..acd321d4b 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -36,6 +36,7 @@ #include "ModrinthModel.h" +#include "Application.h" #include "BuildConfig.h" #include "Json.h" #include "modplatform/ModIndex.h" @@ -91,7 +92,7 @@ auto ModpackListModel::data(const QModelIndex& index, int role) const -> QVarian if (m_logoMap.contains(pack->logoName)) return m_logoMap.value(pack->logoName); - QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); + QIcon icon = QIcon::fromTheme("screenshot-placeholder"); ((ModpackListModel*)this)->requestLogo(pack->logoName, pack->logoUrl); return icon; } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index 600500c6d..4ca41a3e0 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -36,7 +36,6 @@ #pragma once -#include "Application.h" #include "modplatform/ModIndex.h" #include "modplatform/modrinth/ModrinthAPI.h" #include "ui/dialogs/NewInstanceDialog.h" @@ -64,7 +63,7 @@ class ModrinthPage : public QWidget, public ModpackProviderBasePage { ~ModrinthPage() override; QString displayName() const override { return tr("Modrinth"); } - QIcon icon() const override { return APPLICATION->getThemedIcon("modrinth"); } + QIcon icon() const override { return QIcon::fromTheme("modrinth"); } QString id() const override { return "modrinth"; } QString helpPage() const override { return "Modrinth-platform"; } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h index cb0f4d85c..3f41a3d5e 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h @@ -38,8 +38,6 @@ #pragma once -#include "Application.h" - #include "modplatform/ResourceAPI.h" #include "ui/pages/modplatform/DataPackPage.h" @@ -57,7 +55,7 @@ static inline QString displayName() } static inline QIcon icon() { - return APPLICATION->getThemedIcon("modrinth"); + return QIcon::fromTheme("modrinth"); } static inline QString id() { diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index c425044a2..62bad833b 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -71,7 +71,7 @@ QVariant Technic::ListModel::data(const QModelIndex& index, int role) const if (m_logoMap.contains(pack.logoName)) { return (m_logoMap.value(pack.logoName)); } - QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); + QIcon icon = QIcon::fromTheme("screenshot-placeholder"); ((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl); return icon; } diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index 71b6390ef..a131a6db1 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -38,7 +38,6 @@ #include #include -#include #include "TechnicData.h" #include "net/NetJob.h" #include "ui/pages/modplatform/ModpackProviderBasePage.h" @@ -61,7 +60,7 @@ class TechnicPage : public QWidget, public ModpackProviderBasePage { explicit TechnicPage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~TechnicPage(); virtual QString displayName() const override { return "Technic"; } - virtual QIcon icon() const override { return APPLICATION->getThemedIcon("technic"); } + virtual QIcon icon() const override { return QIcon::fromTheme("technic"); } virtual QString id() const override { return "technic"; } virtual QString helpPage() const override { return "Technic-platform"; } virtual bool shouldDisplay() const override; diff --git a/launcher/ui/widgets/JavaWizardWidget.cpp b/launcher/ui/widgets/JavaWizardWidget.cpp index 6158dc7a3..955bc5334 100644 --- a/launcher/ui/widgets/JavaWizardWidget.cpp +++ b/launcher/ui/widgets/JavaWizardWidget.cpp @@ -33,9 +33,9 @@ JavaWizardWidget::JavaWizardWidget(QWidget* parent) : QWidget(parent) { m_availableMemory = Sys::getSystemRam() / Sys::mebibyte; - goodIcon = APPLICATION->getThemedIcon("status-good"); - yellowIcon = APPLICATION->getThemedIcon("status-yellow"); - badIcon = APPLICATION->getThemedIcon("status-bad"); + goodIcon = QIcon::fromTheme("status-good"); + yellowIcon = QIcon::fromTheme("status-yellow"); + badIcon = QIcon::fromTheme("status-bad"); m_memoryTimer = new QTimer(this); setupUi(); @@ -532,7 +532,7 @@ void JavaWizardWidget::updateThresholds() { auto height = m_labelMaxMemIcon->fontInfo().pixelSize(); - QIcon icon = APPLICATION->getThemedIcon(iconName); + QIcon icon = QIcon::fromTheme(iconName); QPixmap pix = icon.pixmap(height, height); m_labelMaxMemIcon->setPixmap(pix); } diff --git a/launcher/ui/widgets/MinecraftSettingsWidget.cpp b/launcher/ui/widgets/MinecraftSettingsWidget.cpp index 9c8e2b405..b738cab74 100644 --- a/launcher/ui/widgets/MinecraftSettingsWidget.cpp +++ b/launcher/ui/widgets/MinecraftSettingsWidget.cpp @@ -500,7 +500,7 @@ void MinecraftSettingsWidget::updateAccountsMenu(const SettingsObject& settings) QIcon face = account->getFace(); if (face.isNull()) - face = APPLICATION->getThemedIcon("noaccount"); + face = QIcon::fromTheme("noaccount"); m_ui->instanceAccountSelector->addItem(face, account->profileName(), i); if (i == accountIndex) diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index e3054c17a..cffda086c 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -228,7 +228,7 @@ void PageContainer::showPage(int row) } else { m_pageStack->setCurrentIndex(0); m_header->setText(QString()); - m_iconHeader->setIcon(APPLICATION->getThemedIcon("bug")); + m_iconHeader->setIcon(QIcon::fromTheme("bug")); } } From 5d46f79f195053817b88356b5e1883e801bab067 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 19 Sep 2025 00:25:26 +0100 Subject: [PATCH 118/118] Fix crash in Rule::apply Signed-off-by: TheKodeToad --- launcher/minecraft/Rule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/Rule.cpp b/launcher/minecraft/Rule.cpp index 1a7c7c768..606776e8a 100644 --- a/launcher/minecraft/Rule.cpp +++ b/launcher/minecraft/Rule.cpp @@ -85,7 +85,7 @@ QJsonObject Rule::toJson() Rule::Action Rule::apply(const RuntimeContext& runtimeContext) { - if (!runtimeContext.classifierMatches(m_os->name)) + if (m_os.has_value() && !runtimeContext.classifierMatches(m_os->name)) return Defer; return m_action;