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); };