diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 7d4430fd2..bc96f57fc 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -39,6 +39,7 @@ set(CORE_SOURCES QVariantUtils.h RuntimeContext.h PSaveFile.h + EnumWrapper.h # Basic instance manipulation tasks (derived from InstanceTask) InstanceCreationTask.h diff --git a/launcher/EnumWrapper.h b/launcher/EnumWrapper.h new file mode 100644 index 000000000..b08d75fe9 --- /dev/null +++ b/launcher/EnumWrapper.h @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2026 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 + +template +struct EnumWrapper { + using Enum = EnumV; + using EnumBase = std::underlying_type_t; + + // NOLINTNEXTLINE(hicpp-explicit-conversions) + constexpr EnumWrapper(Enum e = Derived::invalid()) : m_value(e) {} + + constexpr bool isValid() const { return m_value != Derived::invalid(); } + + bool operator==(const EnumWrapper&) const = default; + + std::strong_ordering operator<=>(const EnumWrapper& other) const { return m_value <=> other.m_value; }; + + std::strong_ordering operator<=>(Enum other) const { return m_value <=> other; } + + QString toString() const + { + for (auto&& [e, name] : Derived::mapping()) { + if (e == m_value) { + return QString(name); + } + } + Q_ASSERT_X(false, "EnumWrapper::toString()", "No string mapping found for current enum value"); + return {}; + } + + static constexpr Derived fromString(const QString& str) + { + for (auto&& [e, name] : Derived::mapping()) { + if (str == name) { + return Derived(e); + } + } + return Derived(Derived::invalid()); + } + + explicit operator EnumBase() const { return static_cast(m_value); } + + explicit operator Enum() const { return m_value; } + + Enum value() const { return m_value; } + + protected: + Enum m_value; +}; \ No newline at end of file diff --git a/launcher/MessageLevel.cpp b/launcher/MessageLevel.cpp index e5f4eb19a..d584975c0 100644 --- a/launcher/MessageLevel.cpp +++ b/launcher/MessageLevel.cpp @@ -1,30 +1,5 @@ #include "MessageLevel.h" -MessageLevel MessageLevel::fromName(const QString& levelName) -{ - QString name = levelName.toUpper(); - if (name == "LAUNCHER") - return MessageLevel::Launcher; - else if (name == "TRACE") - return MessageLevel::Trace; - else if (name == "DEBUG") - return MessageLevel::Debug; - else if (name == "INFO") - return MessageLevel::Info; - else if (name == "MESSAGE") - return MessageLevel::Message; - else if (name == "WARNING" || name == "WARN") - return MessageLevel::Warning; - else if (name == "ERROR" || name == "CRITICAL") - return MessageLevel::Error; - else if (name == "FATAL") - return MessageLevel::Fatal; - // Skip PrePost, it's not exposed to !![]! - // Also skip StdErr and StdOut - else - return MessageLevel::Unknown; -} - MessageLevel MessageLevel::fromQtMsgType(const QtMsgType& type) { switch (type) { diff --git a/launcher/MessageLevel.h b/launcher/MessageLevel.h index cff098664..04ffd954e 100644 --- a/launcher/MessageLevel.h +++ b/launcher/MessageLevel.h @@ -1,43 +1,51 @@ #pragma once #include -#include +#include +#include +#include +#include "EnumWrapper.h" + +enum class MessageLevelValue : std::uint8_t { + Unknown, /**< No idea what this is or where it came from */ + StdOut, /**< Undetermined stderr messages */ + StdErr, /**< Undetermined stdout messages */ + Launcher, /**< Launcher Messages */ + Trace, /**< Trace Messages */ + Debug, /**< Debug Messages */ + Info, /**< Info Messages */ + Message, /**< Standard Messages */ + Warning, /**< Warnings */ + Error, /**< Errors */ + Fatal, /**< Fatal Errors */ +}; /** * @brief the MessageLevel Enum * defines what level a log message is */ -struct MessageLevel { - enum class Enum { - Unknown, /**< No idea what this is or where it came from */ - StdOut, /**< Undetermined stderr messages */ - StdErr, /**< Undetermined stdout messages */ - Launcher, /**< Launcher Messages */ - Trace, /**< Trace Messages */ - Debug, /**< Debug Messages */ - Info, /**< Info Messages */ - Message, /**< Standard Messages */ - Warning, /**< Warnings */ - Error, /**< Errors */ - Fatal, /**< Fatal Errors */ +struct MessageLevel : EnumWrapper { + static constexpr auto invalid() { return Unknown; }; + static constexpr auto mapping() + { + return std::array{ + std::pair{ Unknown, "UNKNOWN" }, std::pair{ Launcher, "LAUNCHER" }, std::pair{ Trace, "TRACE" }, + std::pair{ Debug, "DEBUG" }, std::pair{ Info, "INFO" }, std::pair{ Message, "MESSAGE" }, + std::pair{ Warning, "WARNING" }, std::pair{ Warning, "WARN" }, std::pair{ Error, "ERROR" }, + std::pair{ Error, "CRITICAL" }, std::pair{ Fatal, "FATAL" }, + }; }; - using enum Enum; - constexpr MessageLevel(Enum e = Unknown) : m_type(e) {} - static MessageLevel fromName(const QString& type); + using enum MessageLevelValue; + using Base = EnumWrapper; + using Base::Base; /* inherit ctor */ + + static MessageLevel fromName(const QString& type) { return fromString(type.toUpper()); }; static MessageLevel fromQtMsgType(const QtMsgType& type); static MessageLevel fromLine(const QString& line); - inline bool isValid() const { return m_type != Unknown; } - std::strong_ordering operator<=>(const MessageLevel& other) const = default; - std::strong_ordering operator<=>(const MessageLevel::Enum& other) const { return m_type <=> other; } - explicit operator int() const { return static_cast(m_type); } - explicit operator MessageLevel::Enum() { return m_type; } /* Get message level from a line. Line is modified if it was successful. */ static MessageLevel takeFromLine(QString& line); /* Get message level from a line from the launcher log. Line is modified if it was successful. */ static MessageLevel takeFromLauncherLine(QString& line); - - private: - Enum m_type; }; diff --git a/launcher/launch/LogModel.cpp b/launcher/launch/LogModel.cpp index 117867c1d..d6004f800 100644 --- a/launcher/launch/LogModel.cpp +++ b/launcher/launch/LogModel.cpp @@ -24,7 +24,7 @@ QVariant LogModel::data(const QModelIndex& index, int role) const return m_content[realRow].line; } if (role == LevelRole) { - return static_cast(m_content[realRow].level); + return static_cast(m_content[realRow].level.value()); } return QVariant(); diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index d9e9e901a..7df6b1dc9 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -192,9 +192,9 @@ auto Mod::loaders() const -> QString auto Mod::side() const -> QString { if (metadata()) - return ModPlatform::SideUtils::toString(metadata()->side); + return metadata()->side.toString(); - return ModPlatform::SideUtils::toString(ModPlatform::Side::UniversalSide); + return ModPlatform::SideType(ModPlatform::SideType::UniversalSide).toString(); } auto Mod::mcVersions() const -> QString diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 635b2ae92..0e2d391b6 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -30,10 +30,6 @@ ModLoaderType operator|(ModLoaderType lhs, ModLoaderType rhs) return static_cast(static_cast(lhs) | static_cast(rhs)); } -static const QMap s_indexed_version_type_names = { { "release", IndexedVersionType::Release }, - { "beta", IndexedVersionType::Beta }, - { "alpha", IndexedVersionType::Alpha } }; - static const QList loaderList = { NeoForge, Forge, Cauldron, LiteLoader, Quilt, Fabric, Babric, BTA, LegacyFabric, Ornithe, Rift }; @@ -48,16 +44,6 @@ QList modLoaderTypesToList(ModLoaderTypes flags) return flagList; } -QString IndexedVersionType::toString() const -{ - return s_indexed_version_type_names.key(m_type, "unknown"); -} - -IndexedVersionType IndexedVersionType::fromString(const QString& type) -{ - return s_indexed_version_type_names.value(type, IndexedVersionType::Unknown); -} - const char* ProviderCapabilities::name(ResourceProvider p) { switch (p) { @@ -158,65 +144,4 @@ 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; -} - -QString DependencyTypeUtils::toString(DependencyType type) -{ - switch (type) { - case DependencyType::REQUIRED: - return "REQUIRED"; - case DependencyType::OPTIONAL: - return "OPTIONAL"; - case DependencyType::INCOMPATIBLE: - return "INCOMPATIBLE"; - case DependencyType::EMBEDDED: - return "EMBEDDED"; - case DependencyType::TOOL: - return "TOOL"; - case DependencyType::INCLUDE: - return "INCLUDE"; - case DependencyType::UNKNOWN: - return "UNKNOWN"; - } - return "UNKNOWN"; -} - -DependencyType DependencyTypeUtils::fromString(const QString& str) -{ - static const QHash map = { - { "REQUIRED", DependencyType::REQUIRED }, - { "OPTIONAL", DependencyType::OPTIONAL }, - { "INCOMPATIBLE", DependencyType::INCOMPATIBLE }, - { "EMBEDDED", DependencyType::EMBEDDED }, - { "TOOL", DependencyType::TOOL }, - { "INCLUDE", DependencyType::INCLUDE }, - { "UNKNOWN", DependencyType::UNKNOWN }, - }; - - return map.value(str.toUpper(), DependencyType::UNKNOWN); -} } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 8984e575e..b4e930093 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -23,9 +23,11 @@ #include #include #include -#include +#include #include #include +#include +#include "EnumWrapper.h" class QIODevice; @@ -56,19 +58,48 @@ QList modLoaderTypesToList(ModLoaderTypes flags); enum class ResourceProvider : std::uint8_t { MODRINTH, FLAME }; -enum class DependencyType : std::uint8_t { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE, UNKNOWN }; +enum class DependencyTypeValue : std::uint8_t { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE, UNKNOWN }; +struct DependencyType : EnumWrapper { + static constexpr auto invalid() { return UNKNOWN; }; -enum class Side : std::uint8_t { NoSide = 0, ClientSide = 1U << 0U, ServerSide = 1U << 1U, UniversalSide = ClientSide | ServerSide }; + static constexpr auto mapping() + { + return std::array{ + std::pair{ REQUIRED, "REQUIRED" }, std::pair{ OPTIONAL, "OPTIONAL" }, std::pair{ INCOMPATIBLE, "INCOMPATIBLE" }, + std::pair{ EMBEDDED, "EMBEDDED" }, std::pair{ TOOL, "TOOL" }, std::pair{ INCLUDE, "INCLUDE" }, + std::pair{ UNKNOWN, "UNKNOWN" }, + }; + }; + static DependencyType fromString(const QString& str) + { + return EnumWrapper::fromString(str.toUpper()); + } -namespace SideUtils { -QString toString(Side side); -Side fromString(QString side); -} // namespace SideUtils + using enum DependencyTypeValue; + using Base = EnumWrapper; + using Base::Base; /* inherit ctor */ +}; -namespace DependencyTypeUtils { -QString toString(DependencyType type); -DependencyType fromString(const QString& str); -} // namespace DependencyTypeUtils +enum class SideTypeValue : std::uint8_t { + NoSide = 0, + ClientSide = 1U << 0U, + ServerSide = 1U << 1U, + UniversalSide = ClientSide | ServerSide +}; + +struct SideType : EnumWrapper { + static constexpr auto invalid() { return NoSide; }; + + static constexpr auto mapping() + { + return std::array{ std::pair{ ClientSide, "client" }, std::pair{ ServerSide, "server" }, std::pair{ UniversalSide, "both" }, + std::pair{ NoSide, "" } }; + }; + + using enum SideTypeValue; + using Base = EnumWrapper; + using Base::Base; /* inherit ctor */ +}; namespace ProviderCapabilities { const char* name(ResourceProvider); @@ -87,20 +118,19 @@ struct DonationData { QString url; }; -struct IndexedVersionType { - enum class Enum : std::uint8_t { Unknown = 0, Release = 1, Beta = 2, Alpha = 3 }; - using enum Enum; - constexpr IndexedVersionType(Enum e = Unknown) : m_type(e) {} // NOLINT(hicpp-explicit-conversions) - static IndexedVersionType fromString(const QString& type); - bool isValid() const { return m_type != Unknown; } - std::strong_ordering operator<=>(const IndexedVersionType& other) const = default; - std::strong_ordering operator<=>(const IndexedVersionType::Enum& other) const { return m_type <=> other; } - QString toString() const; - explicit operator int() const { return static_cast(m_type); } - explicit operator IndexedVersionType::Enum() { return m_type; } +enum class IndexedVersionTypeValue : std::uint8_t { Unknown = 0, Release = 1, Beta = 2, Alpha = 3 }; +struct IndexedVersionType : EnumWrapper { + static constexpr auto invalid() { return Unknown; }; - private: - Enum m_type; + static constexpr auto mapping() + { + return std::array{ std::pair{ Unknown, "Unknown" }, std::pair{ Release, "Release" }, std::pair{ Beta, "Beta" }, + std::pair{ Alpha, "Alpha" } }; + }; + + using enum IndexedVersionTypeValue; + using Base = EnumWrapper; + using Base::Base; /* inherit ctor */ }; struct Dependency { @@ -125,7 +155,7 @@ struct IndexedVersion { bool is_preferred = true; QString changelog; QList dependencies; - Side side = Side::NoSide; // this is for flame API + SideType side = SideType::NoSide; // this is for flame API // For internal use, not provided by APIs bool is_currently_selected = false; @@ -173,7 +203,7 @@ struct IndexedPack { QString logoName; QString logoUrl; QString websiteUrl; - Side side = Side::NoSide; + SideType side = SideType::NoSide; bool versionsLoaded = false; QList versions; diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 51b6d4b50..02a20ce50 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -83,7 +83,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 3b0f7f6ae..977ce54bb 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -2,13 +2,9 @@ #include "FileSystem.h" #include "Json.h" -#include "minecraft/MinecraftInstance.h" -#include "minecraft/PackProfile.h" #include "modplatform/ModIndex.h" #include "modplatform/flame/FlameAPI.h" -static FlameAPI api; - void FlameMod::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) { pack.addonId = Json::requireInteger(obj, "id"); @@ -46,30 +42,36 @@ void FlameMod::loadURLs(ModPlatform::IndexedPack& pack, QJsonObject& obj) auto links_obj = obj["links"].toObject(); pack.extraData.issuesUrl = links_obj["issuesUrl"].toString(); - if (pack.extraData.issuesUrl.endsWith('/')) + if (pack.extraData.issuesUrl.endsWith('/')) { pack.extraData.issuesUrl.chop(1); + } pack.extraData.sourceUrl = links_obj["sourceUrl"].toString(); - if (pack.extraData.sourceUrl.endsWith('/')) + if (pack.extraData.sourceUrl.endsWith('/')) { pack.extraData.sourceUrl.chop(1); + } pack.extraData.wikiUrl = links_obj["wikiUrl"].toString(); - if (pack.extraData.wikiUrl.endsWith('/')) + if (pack.extraData.wikiUrl.endsWith('/')) { pack.extraData.wikiUrl.chop(1); + } - if (!pack.extraData.body.isEmpty()) + if (!pack.extraData.body.isEmpty()) { pack.extraDataLoaded = true; + } } void FlameMod::loadBody(ModPlatform::IndexedPack& pack) { - pack.extraData.body = api.getModDescription(pack.addonId.toInt()); + pack.extraData.body = FlameAPI().getModDescription(pack.addonId.toInt()); - if (!pack.extraData.issuesUrl.isEmpty() || !pack.extraData.sourceUrl.isEmpty() || !pack.extraData.wikiUrl.isEmpty()) + if (!pack.extraData.issuesUrl.isEmpty() || !pack.extraData.sourceUrl.isEmpty() || !pack.extraData.wikiUrl.isEmpty()) { pack.extraDataLoaded = true; + } } -static QString enumToString(int hash_algorithm) +namespace { +QString enumToString(int hash_algorithm) { switch (hash_algorithm) { default: @@ -79,6 +81,7 @@ static QString enumToString(int hash_algorithm) return "md5"; } } +} // namespace void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr) { @@ -87,11 +90,13 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArra auto obj = versionIter.toObject(); auto file = loadIndexedPackVersion(obj); - if (!file.addonId.isValid()) + if (!file.addonId.isValid()) { file.addonId = pack.addonId; + } - if (file.fileId.isValid()) // Heuristic to check if the returned value is valid + 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 { @@ -111,27 +116,29 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> for (auto mcVer : versionArray) { auto str = mcVer.toString(); - if (str.contains('.')) + if (str.contains('.')) { file.mcVersion.append(str); + } - file.side = ModPlatform::Side::NoSide; - if (auto loader = str.toLower(); loader == "neoforge") + file.side = ModPlatform::SideType::NoSide; + if (auto loader = str.toLower(); loader == "neoforge") { file.loaders |= ModPlatform::NeoForge; - else if (loader == "forge") + } else if (loader == "forge") { file.loaders |= ModPlatform::Forge; - else if (loader == "cauldron") + } else if (loader == "cauldron") { file.loaders |= ModPlatform::Cauldron; - else if (loader == "liteloader") + } else if (loader == "liteloader") { file.loaders |= ModPlatform::LiteLoader; - else if (loader == "fabric") + } else if (loader == "fabric") { file.loaders |= ModPlatform::Fabric; - else if (loader == "quilt") + } else if (loader == "quilt") { file.loaders |= ModPlatform::Quilt; - else if (loader == "server" || loader == "client") { - 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; + } else if (loader == "server" || loader == "client") { + if (!file.side.isValid()) { + file.side = ModPlatform::SideType::fromString(loader); + } else if (file.side != ModPlatform::SideType::fromString(loader)) { + file.side = ModPlatform::SideType::UniversalSide; + } } } @@ -203,8 +210,9 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> file.dependencies.append(dependency); } - if (load_changelog) - file.changelog = api.getModFileChangelog(file.addonId.toInt(), file.fileId.toInt()); + if (load_changelog) { + file.changelog = FlameAPI().getModFileChangelog(file.addonId.toInt(), file.fileId.toInt()); + } return file; } diff --git a/launcher/modplatform/flame/FlameModIndex.h b/launcher/modplatform/flame/FlameModIndex.h index 2631fab74..fd4facb2a 100644 --- a/launcher/modplatform/flame/FlameModIndex.h +++ b/launcher/modplatform/flame/FlameModIndex.h @@ -6,13 +6,11 @@ #include "modplatform/ModIndex.h" -#include "BaseInstance.h" - namespace FlameMod { -void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj); -void loadURLs(ModPlatform::IndexedPack& m, QJsonObject& obj); -void loadBody(ModPlatform::IndexedPack& m); +void loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj); +void loadURLs(ModPlatform::IndexedPack& pack, QJsonObject& obj); +void loadBody(ModPlatform::IndexedPack& pack); void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr); ModPlatform::IndexedVersion loadIndexedPackVersion(QJsonObject& obj, bool load_changelog = false); } // namespace FlameMod diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 731ac1b09..167f401da 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -70,16 +70,16 @@ class ModrinthAPI : public ResourceAPI { return l.join(','); } - static QString getSideFilters(ModPlatform::Side side) + static QString getSideFilters(ModPlatform::SideType side) { - switch (side) { - case ModPlatform::Side::ClientSide: + switch (side.value()) { + case ModPlatform::SideType::ClientSide: return { R"("client_side:required","client_side:optional"],["server_side:optional","server_side:unsupported")" }; - case ModPlatform::Side::ServerSide: + case ModPlatform::SideTypeValue::ServerSide: return { R"("server_side:required","server_side:optional"],["client_side:optional","client_side:unsupported")" }; - case ModPlatform::Side::UniversalSide: + case ModPlatform::SideTypeValue::UniversalSide: return { R"("client_side:required"],["server_side:required")" }; - case ModPlatform::Side::NoSide: + case ModPlatform::SideTypeValue::NoSide: // fallthrough default: return {}; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 9a972bc85..1c3ff9e92 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -23,11 +23,12 @@ #include #include #include +#include +#include #include "Json.h" #include "MMCZip.h" #include "archive/ExportToZipTask.h" #include "minecraft/PackProfile.h" -#include "minecraft/mod/MetadataHandler.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" #include "modplatform/helpers/HashUtils.h" @@ -51,7 +52,7 @@ ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, , mcInstance(dynamic_cast(instance)) , gameRoot(instance->gameRoot()) , output(output) - , filter(filter) + , filter(std::move(filter)) {} void ModrinthPackExportTask::executeTask() @@ -87,8 +88,9 @@ void ModrinthPackExportTask::collectFiles() if (mcInstance) { mcInstance->loaderModList()->update(); connect(mcInstance->loaderModList(), &ModFolderModel::updateFinished, this, &ModrinthPackExportTask::collectHashes); - } else + } else { collectHashes(); + } } void ModrinthPackExportTask::collectHashes() @@ -99,12 +101,14 @@ void ModrinthPackExportTask::collectHashes() const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types - if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix); })) + if (!std::ranges::any_of(PREFIXES, [&relative](const QString& prefix) { return relative.startsWith(prefix); })) { continue; - if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) { + } + if (!std::ranges::any_of(FILE_EXTENSIONS, [&relative](const QString& extension) { return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled"); - })) + })) { continue; + } QFile openFile(file.absoluteFilePath()); if (!openFile.open(QFile::ReadOnly)) { @@ -151,9 +155,9 @@ void ModrinthPackExportTask::collectHashes() void ModrinthPackExportTask::makeApiRequest() { - if (pendingHashes.isEmpty()) + if (pendingHashes.isEmpty()) { buildZip(); - else { + } else { setStatus(tr("Finding versions for hashes...")); auto [versionsTask, response] = api.currentVersions(pendingHashes.values(), "sha512"); task = versionsTask; @@ -176,17 +180,19 @@ void ModrinthPackExportTask::parseApiResponse(QByteArray* response) iterator.next(); const QJsonObject obj = doc[iterator.value()].toObject(); - if (obj.isEmpty()) + if (obj.isEmpty()) { continue; + } const QJsonArray files_array = obj["files"].toArray(); if (auto fileIter = std::find_if(files_array.begin(), files_array.end(), [&iterator](const QJsonValue& file) { return file["hashes"]["sha512"] == iterator.value(); }); fileIter != files_array.end()) { // map the file to the url - resolvedFiles[iterator.key()] = - ResolvedFile{ fileIter->toObject()["hashes"].toObject()["sha1"].toString(), iterator.value(), - fileIter->toObject()["url"].toString(), fileIter->toObject()["size"].toInt() }; + resolvedFiles[iterator.key()] = ResolvedFile{ .sha1 = fileIter->toObject()["hashes"].toObject()["sha1"].toString(), + .sha512 = iterator.value(), + .url = fileIter->toObject()["url"].toString(), + .size = fileIter->toObject()["size"].toInt() }; } } } catch (const Json::JsonException& e) { @@ -217,7 +223,7 @@ void ModrinthPackExportTask::buildZip() connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) { progressStep->state = TaskStepState::Failed; stepProgress(*progressStep); - emitFailed(reason); + emitFailed(std::move(reason)); }); connect(zipTask.get(), &Task::stepProgress, this, &ModrinthPackExportTask::propagateStepProgress); @@ -226,7 +232,7 @@ void ModrinthPackExportTask::buildZip() stepProgress(*progressStep); }); connect(zipTask.get(), &Task::status, this, [this, progressStep](QString status) { - progressStep->status = status; + progressStep->status = std::move(status); stepProgress(*progressStep); }); task.reset(zipTask); @@ -240,11 +246,12 @@ QByteArray ModrinthPackExportTask::generateIndex() out["game"] = "minecraft"; out["name"] = name; out["versionId"] = version; - if (!summary.isEmpty()) + if (!summary.isEmpty()) { out["summary"] = summary; + } if (mcInstance) { - auto profile = mcInstance->getPackProfile(); + auto* profile = mcInstance->getPackProfile(); // collect all supported components const ComponentPtr minecraft = profile->getComponent("net.minecraft"); const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); @@ -254,16 +261,21 @@ QByteArray ModrinthPackExportTask::generateIndex() // convert all available components to mrpack dependencies QJsonObject dependencies; - if (minecraft != nullptr) + if (minecraft != nullptr) { dependencies["minecraft"] = minecraft->m_version; - if (quilt != nullptr) + } + if (quilt != nullptr) { dependencies["quilt-loader"] = quilt->m_version; - if (fabric != nullptr) + } + if (fabric != nullptr) { dependencies["fabric-loader"] = fabric->m_version; - if (forge != nullptr) + } + if (forge != nullptr) { dependencies["forge"] = forge->m_version; - if (neoForge != nullptr) + } + if (neoForge != nullptr) { dependencies["neoforge"] = neoForge->m_version; + } out["dependencies"] = dependencies; } @@ -291,8 +303,9 @@ 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 == ModPlatform::Side::ClientSide) + if (iterator->side == ModPlatform::SideType::ClientSide) { env["server"] = "unsupported"; + } fileOut["env"] = env; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 5aca657a9..5cf986304 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -46,7 +46,7 @@ class ModrinthPackExportTask : public Task { struct ResolvedFile { QString sha1, sha512, url; qint64 size; - ModPlatform::Side side; + ModPlatform::SideType side; }; static const QStringList PREFIXES; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 48d28feee..a55d44ef1 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -65,11 +65,11 @@ void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) auto server = shouldDownloadOnSide(obj["server_side"].toString()); if (server && client) { - pack.side = ModPlatform::Side::UniversalSide; + pack.side = ModPlatform::SideType::UniversalSide; } else if (server) { - pack.side = ModPlatform::Side::ServerSide; + pack.side = ModPlatform::SideType::ServerSide; } else if (client) { - pack.side = ModPlatform::Side::ClientSide; + pack.side = ModPlatform::SideType::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 4d162a90d..2a1bc904b 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -128,7 +128,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 = mod_version.side == ModPlatform::Side::NoSide ? mod_pack.side : mod_version.side; + mod.side = !mod_version.side.isValid() ? mod_pack.side : mod_version.side; mod.loaders = mod_version.loaders; mod.mcVersions = mod_version.mcVersion; mod.mcVersions.removeDuplicates(); @@ -210,8 +210,7 @@ void V1::updateModIndex(const QDir& index_dir, Mod& mod) toml::array deps; for (auto dep : mod.dependencies) { - auto tbl = toml::table{ { "addonId", dep.addonId.toString().toStdString() }, - { "type", ModPlatform::DependencyTypeUtils::toString(dep.type).toStdString() } }; + auto tbl = toml::table{ { "addonId", dep.addonId.toString().toStdString() }, { "type", dep.type.toString().toStdString() } }; if (!dep.version.isEmpty()) { tbl.emplace("version", dep.version.toStdString()); } @@ -223,7 +222,7 @@ void V1::updateModIndex(const QDir& index_dir, Mod& mod) { auto tbl = toml::table{ { "name", mod.name.toStdString() }, { "filename", mod.filename.toStdString() }, - { "side", ModPlatform::SideUtils::toString(mod.side).toStdString() }, + { "side", mod.side.toString().toStdString() }, { "x-prismlauncher-loaders", loaders }, { "x-prismlauncher-mc-versions", mcVersions }, { "x-prismlauncher-release-type", mod.releaseType.toString().toStdString() }, @@ -300,7 +299,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 = ModPlatform::SideUtils::fromString(stringEntry(table, "side")); + mod.side = ModPlatform::SideType::fromString(stringEntry(table, "side")); mod.releaseType = ModPlatform::IndexedVersionType::fromString(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,7 +370,7 @@ auto V1::getIndexForMod(const QDir& index_dir, QString slug) -> Mod if (dep->contains("version")) { d.version = stringEntry(*dep, "version"); } - d.type = ModPlatform::DependencyTypeUtils::fromString(stringEntry(*dep, "type")); + d.type = ModPlatform::DependencyType::fromString(stringEntry(*dep, "type")); mod.dependencies << d; } } diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index b5b817755..458306e87 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -36,7 +36,7 @@ class V1 { QString slug{}; QString name{}; QString filename{}; - ModPlatform::Side side{ ModPlatform::Side::UniversalSide }; + ModPlatform::SideType side{ ModPlatform::SideType::UniversalSide }; ModPlatform::ModLoaderTypes loaders; QStringList mcVersions; ModPlatform::IndexedVersionType releaseType; diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index c0768b9c3..61be1d69e 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -6,23 +6,30 @@ #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" +#include "minecraft/mod/Mod.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" +#include "modplatform/ResourceType.h" +#include "ui/pages/modplatform/ResourceModel.h" #include +#include +#include #include +#include namespace ResourceDownload { -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) +ModModel::ModModel(BaseInstance& base_inst, ResourceAPI* api, const QString& debugName, QString metaEntryBase) + : ResourceModel(api), m_base_instance(base_inst), m_debugName(debugName + " (Model)"), m_metaEntryBase(std::move(metaEntryBase)) {} /******** Make data requests ********/ ResourceAPI::SearchArgs ModModel::createSearchArguments() { - auto profile = static_cast(m_base_instance).getPackProfile(); + auto* profile = static_cast(m_base_instance).getPackProfile(); Q_ASSERT(profile); Q_ASSERT(m_filter); @@ -32,42 +39,53 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments() auto loaders = profile->getSupportedModLoaders(); // Version filter - if (!m_filter->versions.empty()) + if (!m_filter->versions.empty()) { versions = m_filter->versions; - if (m_filter->loaders) + } + if (m_filter->loaders != 0U) { loaders = m_filter->loaders; - if (!m_filter->categoryIds.empty()) + } + if (!m_filter->categoryIds.empty()) { categories = m_filter->categoryIds; + } auto side = m_filter->side; auto sort = getCurrentSortingMethodByIndex(); - return { - ModPlatform::ResourceType::Mod, m_next_search_offset, m_search_term, sort, loaders, versions, side, categories, m_filter->openSource - }; + return { .type = ModPlatform::ResourceType::Mod, + .offset = m_next_search_offset, + .search = m_search_term, + .sorting = sort, + .loaders = loaders, + .versions = versions, + .side = side, + .categoryIds = categories, + .openSource = m_filter->openSource }; } -ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(const QModelIndex& entry) +ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(const QModelIndex& index) { - auto pack = m_packs[entry.row()]; - auto profile = static_cast(m_base_instance).getPackProfile(); + auto pack = m_packs[index.row()]; + auto* profile = static_cast(m_base_instance).getPackProfile(); Q_ASSERT(profile); Q_ASSERT(m_filter); std::optional> versions{}; auto loaders = profile->getSupportedModLoaders(); - if (!m_filter->versions.empty()) + if (!m_filter->versions.empty()) { versions = m_filter->versions; - if (m_filter->loaders) + } + if (m_filter->loaders != 0U) { loaders = m_filter->loaders; + } - return { pack, versions, loaders, ModPlatform::ResourceType::Mod }; + return { .pack = pack, .mcVersions = versions, .loaders = loaders, .resourceType = ModPlatform::ResourceType::Mod }; } -ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(const QModelIndex& entry) +ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(const QModelIndex& index) { - auto pack = m_packs[entry.row()]; + auto pack = m_packs[index.row()]; return { pack }; } @@ -86,9 +104,10 @@ void ModModel::searchWithTerm(const QString& term, unsigned int sort, bool filte bool ModModel::isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const { auto allMods = static_cast(m_base_instance).loaderModList()->allMods(); - return std::any_of(allMods.cbegin(), allMods.cend(), [pack](Mod* mod) { - if (auto meta = mod->metadata(); meta) + return std::ranges::any_of(allMods, [pack](Mod* mod) { + if (auto meta = mod->metadata(); meta) { return meta->provider == pack->provider && meta->project_id == pack->addonId; + } return false; }); } @@ -96,7 +115,7 @@ bool ModModel::isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const QVariant ModModel::getInstalledPackVersion(ModPlatform::IndexedPack::Ptr pack) const { auto allMods = static_cast(m_base_instance).loaderModList()->allMods(); - for (auto mod : allMods) { + for (auto* mod : allMods) { if (auto meta = mod->metadata(); meta && meta->provider == pack->provider && meta->project_id == pack->addonId) { return meta->version(); } @@ -104,30 +123,36 @@ QVariant ModModel::getInstalledPackVersion(ModPlatform::IndexedPack::Ptr pack) c return {}; } -bool checkSide(ModPlatform::Side filter, ModPlatform::Side value) +namespace { + +bool checkSide(ModPlatform::SideType filter, ModPlatform::SideType value) { - return (filter != ModPlatform::Side::ClientSide && filter != ModPlatform::Side::ServerSide) || - (value != ModPlatform::Side::ClientSide && value != ModPlatform::Side::ServerSide) || filter == value; + return (filter != ModPlatform::SideType::ClientSide && filter != ModPlatform::SideType::ServerSide) || + (value != ModPlatform::SideType::ClientSide && value != ModPlatform::SideType::ServerSide) || filter == value; } +} // namespace bool ModModel::checkFilters(ModPlatform::IndexedPack::Ptr pack) { - if (!m_filter) + if (!m_filter) { return true; + } return !(m_filter->hideInstalled && isPackInstalled(pack)) && checkSide(m_filter->side, pack->side); } bool ModModel::checkVersionFilters(const ModPlatform::IndexedVersion& v) { - if (!m_filter) + if (!m_filter) { return true; + } auto loaders = static_cast(m_base_instance).getPackProfile()->getSupportedModLoaders(); - if (m_filter->loaders) + if (m_filter->loaders != 0U) { loaders = m_filter->loaders; - return (!optedOut(v) && // is opted out(aka curseforge download link) - (!loaders.has_value() || !v.loaders || loaders.value() & v.loaders) && // loaders - checkSide(m_filter->side, v.side) && // side - (m_filter->releases.empty() || // releases + } + return (!optedOut(v) && // is opted out(aka curseforge download link) + (!loaders.has_value() || !v.loaders || ((loaders.value() & v.loaders) != 0U)) && // loaders + checkSide(m_filter->side, v.side) && // side + (m_filter->releases.empty() || // releases std::find(m_filter->releases.cbegin(), m_filter->releases.cend(), v.version_type) != m_filter->releases.cend()) && m_filter->checkMcVersions(v.mcVersion)); // mcVersions } diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index 873d4c1f9..08a858e22 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -5,6 +5,10 @@ #pragma once #include +#include +#include +#include +#include #include "BaseInstance.h" @@ -24,27 +28,27 @@ class ModModel : public ResourceModel { Q_OBJECT public: - ModModel(BaseInstance&, ResourceAPI* api, QString debugName, QString metaEntryBase); + ModModel(BaseInstance&, ResourceAPI* api, const QString& debugName, QString metaEntryBase); /* Ask the API for more information */ void searchWithTerm(const QString& term, unsigned int sort, bool filter_changed); - void setFilter(std::shared_ptr filter) { m_filter = filter; } - virtual QVariant getInstalledPackVersion(ModPlatform::IndexedPack::Ptr) const override; + void setFilter(std::shared_ptr filter) { m_filter = std::move(filter); } + QVariant getInstalledPackVersion(ModPlatform::IndexedPack::Ptr pack) 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; + ResourceAPI::VersionSearchArgs createVersionsArguments(const QModelIndex& index) override; + ResourceAPI::ProjectInfoArgs createInfoArguments(const QModelIndex& index) override; protected: - virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const override; + bool isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const override; - virtual bool checkFilters(ModPlatform::IndexedPack::Ptr) override; - virtual bool checkVersionFilters(const ModPlatform::IndexedVersion&) override; + bool checkFilters(ModPlatform::IndexedPack::Ptr pack) override; + bool checkVersionFilters(const ModPlatform::IndexedVersion& version) override; protected: BaseInstance& m_base_instance; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 861dd9f22..0ee75708e 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -206,7 +206,7 @@ void ListModel::performPaginatedSearch() }; 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 }, + m_filter->versions, ModPlatform::SideType::NoSide, m_filter->categoryIds, m_filter->openSource }, std::move(callbacks)); m_jobPtr = netJob; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 03518c3af..5a2163846 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -174,7 +174,7 @@ void ModpackListModel::performPaginatedSearch() }; 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 }, + m_filter->versions, ModPlatform::SideType::NoSide, m_filter->categoryIds, m_filter->openSource }, std::move(callbacks)); m_jobPtr = netJob; diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index 6fab2b2a5..4b7a4fdb6 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -227,7 +227,7 @@ void ModFilterWidget::prepareBasicFilter() m_filter->openSource = false; if (m_instance) { m_filter->hideInstalled = false; - m_filter->side = ModPlatform::Side::NoSide; // or "both" + m_filter->side = ModPlatform::SideType::NoSide; // or "both" ModPlatform::ModLoaderTypes loaders; if (m_instance->settings()->get("OverrideModDownloadLoaders").toBool()) { for (auto loader : Json::toStringList(m_instance->settings()->get("ModDownloadLoaders").toString())) { @@ -311,16 +311,16 @@ void ModFilterWidget::onLoadersFilterChanged() void ModFilterWidget::onSideFilterChanged() { - ModPlatform::Side side; + ModPlatform::SideType side; if (ui->clientSide->isChecked() && !ui->serverSide->isChecked()) { - side = ModPlatform::Side::ClientSide; + side = ModPlatform::SideType::ClientSide; } else if (!ui->clientSide->isChecked() && ui->serverSide->isChecked()) { - side = ModPlatform::Side::ServerSide; + side = ModPlatform::SideType::ServerSide; } else if (ui->clientSide->isChecked() && ui->serverSide->isChecked()) { - side = ModPlatform::Side::UniversalSide; + side = ModPlatform::SideType::UniversalSide; } else { - side = ModPlatform::Side::NoSide; + side = ModPlatform::SideType::NoSide; } m_filter_changed = side != m_filter->side; diff --git a/launcher/ui/widgets/ModFilterWidget.h b/launcher/ui/widgets/ModFilterWidget.h index 85deb51dc..c7c3bbb35 100644 --- a/launcher/ui/widgets/ModFilterWidget.h +++ b/launcher/ui/widgets/ModFilterWidget.h @@ -61,7 +61,7 @@ class ModFilterWidget : public QTabWidget { std::vector versions; std::vector releases; ModPlatform::ModLoaderTypes loaders; - ModPlatform::Side side; + ModPlatform::SideType side; bool hideInstalled; QStringList categoryIds; bool openSource; diff --git a/tests/Packwiz_test.cpp b/tests/Packwiz_test.cpp index 1fcb1b9f9..a081b7e07 100644 --- a/tests/Packwiz_test.cpp +++ b/tests/Packwiz_test.cpp @@ -43,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, ModPlatform::Side::ClientSide); + QCOMPARE(metadata.side, ModPlatform::SideType::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"); @@ -73,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, ModPlatform::Side::UniversalSide); + QCOMPARE(metadata.side, ModPlatform::SideType::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");