From a3de20eea53ede611fd26d730ce8ed4643ad7544 Mon Sep 17 00:00:00 2001 From: Collecting Date: Sat, 17 Jan 2026 01:57:08 +0000 Subject: [PATCH] add: Nx-Optimizer Signed-off-by: Collecting --- src/citron/mod_manager/mod_service.cpp | 87 ++++++++++++++++---------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/src/citron/mod_manager/mod_service.cpp b/src/citron/mod_manager/mod_service.cpp index 60c728205..137ba0f39 100644 --- a/src/citron/mod_manager/mod_service.cpp +++ b/src/citron/mod_manager/mod_service.cpp @@ -17,10 +17,17 @@ ModService::ModService(QObject* parent) : QObject(parent) { ModService::~ModService() = default; void ModService::FetchAvailableMods(const QString& title_id) { - QNetworkRequest request{QUrl(MANIFEST_URL)}; + const QStringList optimizer_supported = { + QStringLiteral("01006BB00C6F0000"), QStringLiteral("0100F2C0115B6000"), + QStringLiteral("01002B00111A2000"), QStringLiteral("01007EF00011E000"), + QStringLiteral("0100F43008C44000"), QStringLiteral("0100A3D008C5C000"), + QStringLiteral("01008F6008C5E000") + }; + + QNetworkRequest request((QUrl(MANIFEST_URL))); QNetworkReply* reply = network_manager->get(request); - connect(reply, &QNetworkReply::finished, this, [this, reply, title_id]() { + connect(reply, &QNetworkReply::finished, this, [this, reply, title_id, optimizer_supported]() { if (reply->error() != QNetworkReply::NoError) { emit Error(reply->errorString()); reply->deleteLater(); @@ -29,47 +36,59 @@ void ModService::FetchAvailableMods(const QString& title_id) { QJsonDocument doc = QJsonDocument::fromJson(reply->readAll()); QJsonObject root = doc.object(); - - // Convert title_id to uppercase to match your folder/manifest structure QString tid_upper = title_id.toUpper(); - if (!root.contains(tid_upper)) { - emit Error(QStringLiteral("No mods found for this game in the repository.")); - reply->deleteLater(); - return; - } ModUpdateInfo info; info.title_id = title_id; - QJsonObject tid_obj = root.value(tid_upper).toObject(); - QJsonObject versions_obj = tid_obj.value(QStringLiteral("versions")).toObject(); - - // Loop through every version found for this game (e.g., 1.0.0, 2.0.0) - for (auto it = versions_obj.begin(); it != versions_obj.end(); ++it) { - QString v_name = it.key(); - QJsonObject v_data = it.value().toObject(); - QJsonArray patches_array = v_data.value(QStringLiteral("patches")).toArray(); - - std::vector patches; - for (const QJsonValue& val : patches_array) { - QJsonObject p_obj = val.toObject(); - ModPatch patch; - patch.name = p_obj.value(QStringLiteral("name")).toString(); - patch.type = p_obj.value(QStringLiteral("type")).toString(); - patch.rel_path = p_obj.value(QStringLiteral("rel_path")).toString(); - - QJsonArray files_arr = p_obj.value(QStringLiteral("files")).toArray(); - for (const QJsonValue& f : files_arr) { - patch.files << f.toString(); + // 1. Process standard mods from manifest + if (root.contains(tid_upper)) { + QJsonObject tid_obj = root.value(tid_upper).toObject(); + QJsonObject versions_obj = tid_obj.value(QStringLiteral("versions")).toObject(); + for (auto it = versions_obj.begin(); it != versions_obj.end(); ++it) { + QString v_name = it.key(); + QJsonObject v_data = it.value().toObject(); + QJsonArray patches_array = v_data.value(QStringLiteral("patches")).toArray(); + std::vector patches; + for (const QJsonValue& val : patches_array) { + QJsonObject p_obj = val.toObject(); + ModPatch patch; + patch.name = p_obj.value(QStringLiteral("name")).toString(); + patch.type = p_obj.value(QStringLiteral("type")).toString(); + patch.rel_path = p_obj.value(QStringLiteral("rel_path")).toString(); + QJsonArray files_arr = p_obj.value(QStringLiteral("files")).toArray(); + for (const QJsonValue& f : files_arr) patch.files << f.toString(); + patches.push_back(patch); } - - patches.push_back(patch); + info.version_patches[v_name] = patches; } - // Add this version and its mods to the map - info.version_patches[v_name] = patches; } - emit ModsAvailable(info); + // 2. Also Fetch NX-Optimizer if supported + if (optimizer_supported.contains(tid_upper)) { + QNetworkRequest github_req(QUrl(QStringLiteral("https://api.github.com/repos/MaxLastBreath/nx-optimizer/releases/latest"))); + github_req.setRawHeader("Accept", "application/vnd.github.v3+json"); + github_req.setRawHeader("User-Agent", "Citron-Emulator"); + QNetworkReply* github_reply = network_manager->get(github_req); + + connect(github_reply, &QNetworkReply::finished, this, [this, github_reply, info]() mutable { + if (github_reply->error() == QNetworkReply::NoError) { + QJsonObject release = QJsonDocument::fromJson(github_reply->readAll()).object(); + QJsonArray assets = release.value(QStringLiteral("assets")).toArray(); + ModPatch tool; + tool.name = QStringLiteral("NX-Optimizer by MaxLastBreath"); + tool.type = QStringLiteral("tool"); + for (const QJsonValue& asset : assets) { + tool.files << asset.toObject().value(QStringLiteral("browser_download_url")).toString(); + } + info.version_patches[QStringLiteral("Global Tools")].push_back(tool); + } + emit ModsAvailable(info); + github_reply->deleteLater(); + }); + } else { + emit ModsAvailable(info); + } reply->deleteLater(); }); }