From 3d84635b24e52c35b70e044bed67060adb1dcfd6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 26 Oct 2023 20:09:12 +0300 Subject: [PATCH 01/37] Remove file on mod duplication Signed-off-by: Trial97 --- launcher/InstanceList.cpp | 12 ++++++------ launcher/InstanceList.h | 2 +- launcher/minecraft/mod/Resource.cpp | 10 +++++----- launcher/minecraft/mod/ResourceFolderModel.cpp | 3 --- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index 756ff93ddc..e245fc2c69 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -371,13 +371,13 @@ void InstanceList::undoTrashInstance() auto top = m_trashHistory.pop(); - while (QDir(top.polyPath).exists()) { + while (QDir(top.rootPath).exists()) { top.id += "1"; - top.polyPath += "1"; + top.rootPath += "1"; } - qDebug() << "Moving" << top.trashPath << "back to" << top.polyPath; - QFile(top.trashPath).rename(top.polyPath); + qDebug() << "Moving" << top.trashPath << "back to" << top.rootPath; + QFile(top.trashPath).rename(top.rootPath); m_instanceGroupIndex[top.id] = top.groupName; increaseGroupCount(top.groupName); @@ -634,8 +634,8 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id) QString inst_type = instanceSettings->get("InstanceType").toString(); - // NOTE: Some PolyMC versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a OneSix - // instance + // NOTE: Some PrismLauncher versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a + // OneSix instance if (inst_type == "OneSix" || inst_type.isEmpty()) { inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot)); } else { diff --git a/launcher/InstanceList.h b/launcher/InstanceList.h index 6b0bcd8109..1a70b57b96 100644 --- a/launcher/InstanceList.h +++ b/launcher/InstanceList.h @@ -58,7 +58,7 @@ enum class GroupsState { NotLoaded, Steady, Dirty }; struct TrashHistoryItem { QString id; - QString polyPath; + QString rootPath; QString trashPath; QString groupName; }; diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index da806f0f46..05940fcb45 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -130,15 +130,15 @@ bool Resource::enable(EnableAction action) if (!path.endsWith(".disabled")) return false; path.chop(9); - - if (!file.rename(path)) - return false; } else { path += ".disabled"; - - if (!file.rename(path)) + } + if (QFileInfo::exists(path)) { // the path exists so just remove the file at path + if (!QFile::remove(path)) return false; } + if (!file.rename(path)) + return false; setFile(QFileInfo(path)); diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 0503b660bb..8f2c87747b 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -213,9 +213,6 @@ bool ResourceFolderModel::setResourceEnabled(const QModelIndexList& indexes, Ena } auto new_id = resource->internal_id(); - if (m_resources_index.contains(new_id)) { - // FIXME: https://github.com/PolyMC/PolyMC/issues/550 - } m_resources_index.remove(old_id); m_resources_index[new_id] = row; From 60a7628dbbf21c27cdc8021b01278b173f56dedb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 26 Oct 2023 20:43:26 +0300 Subject: [PATCH 02/37] delete duplicate mods Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/BasicFolderLoadTask.h | 10 ++++++++-- launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h b/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h index 23a2b649ab..6e8b8ed43c 100644 --- a/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h @@ -49,10 +49,16 @@ class BasicFolderLoadTask : public Task { connect(this, &Task::finished, this->thread(), &QThread::quit); m_dir.refresh(); + QStringList names; for (auto entry : m_dir.entryInfoList()) { auto resource = m_create_func(entry); - resource->moveToThread(m_thread_to_spawn_into); - m_result->resources.insert(resource->internal_id(), resource); + if (names.contains(resource->name())) { + resource->destroy(); + } else { + names << resource->name(); + resource->moveToThread(m_thread_to_spawn_into); + m_result->resources.insert(resource->internal_id(), resource); + } } if (m_aborted) diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index 2094df4fcf..c11759dd2f 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -62,9 +62,15 @@ void ModFolderLoadTask::executeTask() // Read JAR files that don't have metadata m_mods_dir.refresh(); + QStringList names; for (auto entry : m_mods_dir.entryInfoList()) { Mod* mod(new Mod(entry)); + if (names.contains(mod->name())) { + mod->destroy(m_index_dir, true); + continue; + } + names << mod->name(); if (mod->enabled()) { if (m_result->mods.contains(mod->internal_id())) { m_result->mods[mod->internal_id()]->setStatus(ModStatus::Installed); From 76a656a017b67453e15c669671b453cfdfd0e7f9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 18 May 2024 22:27:11 +0300 Subject: [PATCH 03/37] retry auth step on fail Signed-off-by: Trial97 --- .../minecraft/auth/steps/EntitlementsStep.cpp | 10 +++-- .../minecraft/auth/steps/EntitlementsStep.h | 4 +- launcher/minecraft/auth/steps/GetSkinStep.cpp | 9 +++-- launcher/minecraft/auth/steps/GetSkinStep.h | 4 +- .../auth/steps/LauncherLoginStep.cpp | 20 ++++++---- .../minecraft/auth/steps/LauncherLoginStep.h | 4 +- .../auth/steps/MSADeviceCodeStep.cpp | 29 ++++++++------- .../minecraft/auth/steps/MSADeviceCodeStep.h | 4 +- .../auth/steps/MinecraftProfileStep.cpp | 26 +++++++------ .../auth/steps/MinecraftProfileStep.h | 4 +- .../auth/steps/XboxAuthorizationStep.cpp | 23 +++++++----- .../auth/steps/XboxAuthorizationStep.h | 4 +- .../minecraft/auth/steps/XboxProfileStep.cpp | 19 ++++++---- .../minecraft/auth/steps/XboxProfileStep.h | 4 +- .../minecraft/auth/steps/XboxUserStep.cpp | 19 ++++++---- launcher/minecraft/auth/steps/XboxUserStep.h | 4 +- launcher/net/NetJob.cpp | 37 +++++++++++-------- launcher/net/NetJob.h | 2 + 18 files changed, 139 insertions(+), 87 deletions(-) diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.cpp b/launcher/minecraft/auth/steps/EntitlementsStep.cpp index 19cbe6898c..4c4809fae7 100644 --- a/launcher/minecraft/auth/steps/EntitlementsStep.cpp +++ b/launcher/minecraft/auth/steps/EntitlementsStep.cpp @@ -10,6 +10,7 @@ #include "Logging.h" #include "minecraft/auth/Parsers.h" #include "net/Download.h" +#include "net/NetJob.h" #include "net/StaticHeaderProxy.h" #include "tasks/Task.h" @@ -31,12 +32,15 @@ void EntitlementsStep::perform() { "Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8() } }; m_response.reset(new QByteArray()); - m_task = Net::Download::makeByteArray(url, m_response); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_request = Net::Download::makeByteArray(url, m_response); + m_request->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + + m_task.reset(new NetJob("EntitlementsStep", APPLICATION->network())); + m_task->setAskRetry(false); + m_task->addNetAction(m_request); connect(m_task.get(), &Task::finished, this, &EntitlementsStep::onRequestDone); - m_task->setNetwork(APPLICATION->network()); m_task->start(); qDebug() << "Getting entitlements..."; } diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.h b/launcher/minecraft/auth/steps/EntitlementsStep.h index dd8ec7aaa4..f20fcac088 100644 --- a/launcher/minecraft/auth/steps/EntitlementsStep.h +++ b/launcher/minecraft/auth/steps/EntitlementsStep.h @@ -4,6 +4,7 @@ #include "minecraft/auth/AuthStep.h" #include "net/Download.h" +#include "net/NetJob.h" class EntitlementsStep : public AuthStep { Q_OBJECT @@ -22,5 +23,6 @@ class EntitlementsStep : public AuthStep { private: QString m_entitlements_request_id; std::shared_ptr m_response; - Net::Download::Ptr m_task; + Net::Download::Ptr m_request; + NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/GetSkinStep.cpp b/launcher/minecraft/auth/steps/GetSkinStep.cpp index d9785b16a1..a0c039cead 100644 --- a/launcher/minecraft/auth/steps/GetSkinStep.cpp +++ b/launcher/minecraft/auth/steps/GetSkinStep.cpp @@ -17,17 +17,20 @@ void GetSkinStep::perform() QUrl url(m_data->minecraftProfile.skin.url); m_response.reset(new QByteArray()); - m_task = Net::Download::makeByteArray(url, m_response); + m_request = Net::Download::makeByteArray(url, m_response); + + m_task.reset(new NetJob("GetSkinStep", APPLICATION->network())); + m_task->setAskRetry(false); + m_task->addNetAction(m_request); connect(m_task.get(), &Task::finished, this, &GetSkinStep::onRequestDone); - m_task->setNetwork(APPLICATION->network()); m_task->start(); } void GetSkinStep::onRequestDone() { - if (m_task->error() == QNetworkReply::NoError) + if (m_request->error() == QNetworkReply::NoError) m_data->minecraftProfile.skin.data = *m_response; emit finished(AccountTaskState::STATE_SUCCEEDED, tr("Got skin")); } diff --git a/launcher/minecraft/auth/steps/GetSkinStep.h b/launcher/minecraft/auth/steps/GetSkinStep.h index fffd8be039..c598f05d9d 100644 --- a/launcher/minecraft/auth/steps/GetSkinStep.h +++ b/launcher/minecraft/auth/steps/GetSkinStep.h @@ -4,6 +4,7 @@ #include "minecraft/auth/AuthStep.h" #include "net/Download.h" +#include "net/NetJob.h" class GetSkinStep : public AuthStep { Q_OBJECT @@ -21,5 +22,6 @@ class GetSkinStep : public AuthStep { private: std::shared_ptr m_response; - Net::Download::Ptr m_task; + Net::Download::Ptr m_request; + NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp index d72346c74a..08e1b3b1f0 100644 --- a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp +++ b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp @@ -37,12 +37,15 @@ void LauncherLoginStep::perform() }; m_response.reset(new QByteArray()); - m_task = Net::Upload::makeByteArray(url, m_response, requestBody.toUtf8()); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_request = Net::Upload::makeByteArray(url, m_response, requestBody.toUtf8()); + m_request->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + + m_task.reset(new NetJob("LauncherLoginStep", APPLICATION->network())); + m_task->setAskRetry(false); + m_task->addNetAction(m_request); connect(m_task.get(), &Task::finished, this, &LauncherLoginStep::onRequestDone); - m_task->setNetwork(APPLICATION->network()); m_task->start(); qDebug() << "Getting Minecraft access token..."; } @@ -50,12 +53,13 @@ void LauncherLoginStep::perform() void LauncherLoginStep::onRequestDone() { qCDebug(authCredentials()) << *m_response; - if (m_task->error() != QNetworkReply::NoError) { - qWarning() << "Reply error:" << m_task->error(); - if (Net::isApplicationError(m_task->error())) { - emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to get Minecraft access token: %1").arg(m_task->errorString())); + if (m_request->error() != QNetworkReply::NoError) { + qWarning() << "Reply error:" << m_request->error(); + if (Net::isApplicationError(m_request->error())) { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Failed to get Minecraft access token: %1").arg(m_request->errorString())); } else { - emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to get Minecraft access token: %1").arg(m_task->errorString())); + emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to get Minecraft access token: %1").arg(m_request->errorString())); } return; } diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.h b/launcher/minecraft/auth/steps/LauncherLoginStep.h index 21a2a49202..0b5969f2b9 100644 --- a/launcher/minecraft/auth/steps/LauncherLoginStep.h +++ b/launcher/minecraft/auth/steps/LauncherLoginStep.h @@ -3,6 +3,7 @@ #include #include "minecraft/auth/AuthStep.h" +#include "net/NetJob.h" #include "net/Upload.h" class LauncherLoginStep : public AuthStep { @@ -21,5 +22,6 @@ class LauncherLoginStep : public AuthStep { private: std::shared_ptr m_response; - Net::Upload::Ptr m_task; + Net::Upload::Ptr m_request; + NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp index 22f5d40693..ebb9b66531 100644 --- a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp +++ b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp @@ -65,12 +65,15 @@ void MSADeviceCodeStep::perform() { "Accept", "application/json" }, }; m_response.reset(new QByteArray()); - m_task = Net::Upload::makeByteArray(url, m_response, payload); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_request = Net::Upload::makeByteArray(url, m_response, payload); + m_request->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + + m_task.reset(new NetJob("MSADeviceCodeStep", APPLICATION->network())); + m_task->setAskRetry(false); + m_task->addNetAction(m_request); connect(m_task.get(), &Task::finished, this, &MSADeviceCodeStep::deviceAutorizationFinished); - m_task->setNetwork(APPLICATION->network()); m_task->start(); } @@ -115,7 +118,7 @@ void MSADeviceCodeStep::deviceAutorizationFinished() tr("Device authorization failed: %1").arg(rsp.error_description.isEmpty() ? rsp.error : rsp.error_description)); return; } - if (!m_task->wasSuccessful() || m_task->error() != QNetworkReply::NoError) { + if (!m_request->wasSuccessful() || m_request->error() != QNetworkReply::NoError) { emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Failed to retrieve device authorization")); qDebug() << *m_response; return; @@ -145,8 +148,8 @@ void MSADeviceCodeStep::abort() { m_expiration_timer.stop(); m_pool_timer.stop(); - if (m_task) { - m_task->abort(); + if (m_request) { + m_request->abort(); } m_is_aborted = true; emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Task aborted")); @@ -175,13 +178,13 @@ void MSADeviceCodeStep::authenticateUser() { "Accept", "application/json" }, }; m_response.reset(new QByteArray()); - m_task = Net::Upload::makeByteArray(url, m_response, payload); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_request = Net::Upload::makeByteArray(url, m_response, payload); + m_request->addHeaderProxy(new Net::StaticHeaderProxy(headers)); - connect(m_task.get(), &Task::finished, this, &MSADeviceCodeStep::authenticationFinished); + connect(m_request.get(), &Task::finished, this, &MSADeviceCodeStep::authenticationFinished); - m_task->setNetwork(APPLICATION->network()); - m_task->start(); + m_request->setNetwork(APPLICATION->network()); + m_request->start(); } struct AuthenticationResponse { @@ -221,7 +224,7 @@ AuthenticationResponse parseAuthenticationResponse(const QByteArray& data) void MSADeviceCodeStep::authenticationFinished() { - if (m_task->error() == QNetworkReply::TimeoutError) { + if (m_request->error() == QNetworkReply::TimeoutError) { // rfc8628#section-3.5 // "On encountering a connection timeout, clients MUST unilaterally // reduce their polling frequency before retrying. The use of an @@ -254,7 +257,7 @@ void MSADeviceCodeStep::authenticationFinished() tr("Device Access failed: %1").arg(rsp.error_description.isEmpty() ? rsp.error : rsp.error_description)); return; } - if (!m_task->wasSuccessful() || m_task->error() != QNetworkReply::NoError) { + if (!m_request->wasSuccessful() || m_request->error() != QNetworkReply::NoError) { startPoolTimer(); // it failed so just try again without increasing the interval return; } diff --git a/launcher/minecraft/auth/steps/MSADeviceCodeStep.h b/launcher/minecraft/auth/steps/MSADeviceCodeStep.h index e53eebc628..87e0ce6e2b 100644 --- a/launcher/minecraft/auth/steps/MSADeviceCodeStep.h +++ b/launcher/minecraft/auth/steps/MSADeviceCodeStep.h @@ -38,6 +38,7 @@ #include #include "minecraft/auth/AuthStep.h" +#include "net/NetJob.h" #include "net/Upload.h" class MSADeviceCodeStep : public AuthStep { @@ -72,5 +73,6 @@ class MSADeviceCodeStep : public AuthStep { QTimer m_expiration_timer; std::shared_ptr m_response; - Net::Upload::Ptr m_task; + Net::Upload::Ptr m_request; + NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp index 305f44320a..81b6511f51 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp @@ -22,37 +22,41 @@ void MinecraftProfileStep::perform() { "Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8() } }; m_response.reset(new QByteArray()); - m_task = Net::Download::makeByteArray(url, m_response); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_request = Net::Download::makeByteArray(url, m_response); + m_request->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + + m_task.reset(new NetJob("MinecraftProfileStep", APPLICATION->network())); + m_task->setAskRetry(false); + m_task->addNetAction(m_request); connect(m_task.get(), &Task::finished, this, &MinecraftProfileStep::onRequestDone); - m_task->setNetwork(APPLICATION->network()); m_task->start(); } void MinecraftProfileStep::onRequestDone() { - if (m_task->error() == QNetworkReply::ContentNotFoundError) { + if (m_request->error() == QNetworkReply::ContentNotFoundError) { // NOTE: Succeed even if we do not have a profile. This is a valid account state. m_data->minecraftProfile = MinecraftProfile(); emit finished(AccountTaskState::STATE_SUCCEEDED, tr("Account has no Minecraft profile.")); return; } - if (m_task->error() != QNetworkReply::NoError) { + if (m_request->error() != QNetworkReply::NoError) { qWarning() << "Error getting profile:"; - qWarning() << " HTTP Status: " << m_task->replyStatusCode(); - qWarning() << " Internal error no.: " << m_task->error(); - qWarning() << " Error string: " << m_task->errorString(); + qWarning() << " HTTP Status: " << m_request->replyStatusCode(); + qWarning() << " Internal error no.: " << m_request->error(); + qWarning() << " Error string: " << m_request->errorString(); qWarning() << " Response:"; qWarning() << QString::fromUtf8(*m_response); - if (Net::isApplicationError(m_task->error())) { + if (Net::isApplicationError(m_request->error())) { emit finished(AccountTaskState::STATE_FAILED_SOFT, - tr("Minecraft Java profile acquisition failed: %1").arg(m_task->errorString())); + tr("Minecraft Java profile acquisition failed: %1").arg(m_request->errorString())); } else { - emit finished(AccountTaskState::STATE_OFFLINE, tr("Minecraft Java profile acquisition failed: %1").arg(m_task->errorString())); + emit finished(AccountTaskState::STATE_OFFLINE, + tr("Minecraft Java profile acquisition failed: %1").arg(m_request->errorString())); } return; } diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.h b/launcher/minecraft/auth/steps/MinecraftProfileStep.h index 831cd52f7b..e8b35b8753 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.h +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.h @@ -4,6 +4,7 @@ #include "minecraft/auth/AuthStep.h" #include "net/Download.h" +#include "net/NetJob.h" class MinecraftProfileStep : public AuthStep { Q_OBJECT @@ -21,5 +22,6 @@ class MinecraftProfileStep : public AuthStep { private: std::shared_ptr m_response; - Net::Download::Ptr m_task; + Net::Download::Ptr m_request; + NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp index f072209865..4f5f14a33f 100644 --- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp +++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp @@ -42,12 +42,15 @@ void XboxAuthorizationStep::perform() { "Accept", "application/json" }, }; m_response.reset(new QByteArray()); - m_task = Net::Upload::makeByteArray(url, m_response, xbox_auth_data.toUtf8()); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_request = Net::Upload::makeByteArray(url, m_response, xbox_auth_data.toUtf8()); + m_request->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + + m_task.reset(new NetJob("XboxAuthorizationStep", APPLICATION->network())); + m_task->setAskRetry(false); + m_task->addNetAction(m_request); connect(m_task.get(), &Task::finished, this, &XboxAuthorizationStep::onRequestDone); - m_task->setNetwork(APPLICATION->network()); m_task->start(); qDebug() << "Getting authorization token for " << m_relyingParty; } @@ -55,19 +58,19 @@ void XboxAuthorizationStep::perform() void XboxAuthorizationStep::onRequestDone() { qCDebug(authCredentials()) << *m_response; - if (m_task->error() != QNetworkReply::NoError) { - qWarning() << "Reply error:" << m_task->error(); - if (Net::isApplicationError(m_task->error())) { + if (m_request->error() != QNetworkReply::NoError) { + qWarning() << "Reply error:" << m_request->error(); + if (Net::isApplicationError(m_request->error())) { if (!processSTSError()) { emit finished(AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, m_task->error())); + tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, m_request->error())); } else { emit finished(AccountTaskState::STATE_FAILED_SOFT, - tr("Unknown STS error for %1 services: %2").arg(m_authorizationKind, m_task->errorString())); + tr("Unknown STS error for %1 services: %2").arg(m_authorizationKind, m_request->errorString())); } } else { emit finished(AccountTaskState::STATE_OFFLINE, - tr("Failed to get authorization for %1 services: %2").arg(m_authorizationKind, m_task->errorString())); + tr("Failed to get authorization for %1 services: %2").arg(m_authorizationKind, m_request->errorString())); } return; } @@ -92,7 +95,7 @@ void XboxAuthorizationStep::onRequestDone() bool XboxAuthorizationStep::processSTSError() { - if (m_task->error() == QNetworkReply::AuthenticationRequiredError) { + if (m_request->error() == QNetworkReply::AuthenticationRequiredError) { QJsonParseError jsonError; QJsonDocument doc = QJsonDocument::fromJson(*m_response, &jsonError); if (jsonError.error) { diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.h b/launcher/minecraft/auth/steps/XboxAuthorizationStep.h index f6329b7f07..8418727c48 100644 --- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.h +++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.h @@ -3,6 +3,7 @@ #include #include "minecraft/auth/AuthStep.h" +#include "net/NetJob.h" #include "net/Upload.h" class XboxAuthorizationStep : public AuthStep { @@ -28,5 +29,6 @@ class XboxAuthorizationStep : public AuthStep { QString m_authorizationKind; std::shared_ptr m_response; - Net::Upload::Ptr m_task; + Net::Upload::Ptr m_request; + NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/XboxProfileStep.cpp b/launcher/minecraft/auth/steps/XboxProfileStep.cpp index 440a4657c8..a784fa1959 100644 --- a/launcher/minecraft/auth/steps/XboxProfileStep.cpp +++ b/launcher/minecraft/auth/steps/XboxProfileStep.cpp @@ -34,25 +34,28 @@ void XboxProfileStep::perform() }; m_response.reset(new QByteArray()); - m_task = Net::Download::makeByteArray(url, m_response); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_request = Net::Download::makeByteArray(url, m_response); + m_request->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + + m_task.reset(new NetJob("XboxProfileStep", APPLICATION->network())); + m_task->setAskRetry(false); + m_task->addNetAction(m_request); connect(m_task.get(), &Task::finished, this, &XboxProfileStep::onRequestDone); - m_task->setNetwork(APPLICATION->network()); m_task->start(); qDebug() << "Getting Xbox profile..."; } void XboxProfileStep::onRequestDone() { - if (m_task->error() != QNetworkReply::NoError) { - qWarning() << "Reply error:" << m_task->error(); + if (m_request->error() != QNetworkReply::NoError) { + qWarning() << "Reply error:" << m_request->error(); qCDebug(authCredentials()) << *m_response; - if (Net::isApplicationError(m_task->error())) { - emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to retrieve the Xbox profile: %1").arg(m_task->errorString())); + if (Net::isApplicationError(m_request->error())) { + emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to retrieve the Xbox profile: %1").arg(m_request->errorString())); } else { - emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to retrieve the Xbox profile: %1").arg(m_task->errorString())); + emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to retrieve the Xbox profile: %1").arg(m_request->errorString())); } return; } diff --git a/launcher/minecraft/auth/steps/XboxProfileStep.h b/launcher/minecraft/auth/steps/XboxProfileStep.h index dfa273d9c3..f2ab874f22 100644 --- a/launcher/minecraft/auth/steps/XboxProfileStep.h +++ b/launcher/minecraft/auth/steps/XboxProfileStep.h @@ -4,6 +4,7 @@ #include "minecraft/auth/AuthStep.h" #include "net/Download.h" +#include "net/NetJob.h" class XboxProfileStep : public AuthStep { Q_OBJECT @@ -21,5 +22,6 @@ class XboxProfileStep : public AuthStep { private: std::shared_ptr m_response; - Net::Download::Ptr m_task; + Net::Download::Ptr m_request; + NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/XboxUserStep.cpp b/launcher/minecraft/auth/steps/XboxUserStep.cpp index c9453dba14..3e697b5060 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.cpp +++ b/launcher/minecraft/auth/steps/XboxUserStep.cpp @@ -38,24 +38,27 @@ void XboxUserStep::perform() { "x-xbl-contract-version", "1" } }; m_response.reset(new QByteArray()); - m_task = Net::Upload::makeByteArray(url, m_response, xbox_auth_data.toUtf8()); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_request = Net::Upload::makeByteArray(url, m_response, xbox_auth_data.toUtf8()); + m_request->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + + m_task.reset(new NetJob("XboxUserStep", APPLICATION->network())); + m_task->setAskRetry(false); + m_task->addNetAction(m_request); connect(m_task.get(), &Task::finished, this, &XboxUserStep::onRequestDone); - m_task->setNetwork(APPLICATION->network()); m_task->start(); qDebug() << "First layer of XBox auth ... commencing."; } void XboxUserStep::onRequestDone() { - if (m_task->error() != QNetworkReply::NoError) { - qWarning() << "Reply error:" << m_task->error(); - if (Net::isApplicationError(m_task->error())) { - emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication failed: %1").arg(m_task->errorString())); + if (m_request->error() != QNetworkReply::NoError) { + qWarning() << "Reply error:" << m_request->error(); + if (Net::isApplicationError(m_request->error())) { + emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication failed: %1").arg(m_request->errorString())); } else { - emit finished(AccountTaskState::STATE_OFFLINE, tr("XBox user authentication failed: %1").arg(m_task->errorString())); + emit finished(AccountTaskState::STATE_OFFLINE, tr("XBox user authentication failed: %1").arg(m_request->errorString())); } return; } diff --git a/launcher/minecraft/auth/steps/XboxUserStep.h b/launcher/minecraft/auth/steps/XboxUserStep.h index 934a00c526..f6cc822f20 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.h +++ b/launcher/minecraft/auth/steps/XboxUserStep.h @@ -3,6 +3,7 @@ #include #include "minecraft/auth/AuthStep.h" +#include "net/NetJob.h" #include "net/Upload.h" class XboxUserStep : public AuthStep { @@ -21,5 +22,6 @@ class XboxUserStep : public AuthStep { private: std::shared_ptr m_response; - Net::Upload::Ptr m_task; + Net::Upload::Ptr m_request; + NetJob::Ptr m_task; }; diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp index 65d6ec3a43..e8df8c3a8d 100644 --- a/launcher/net/NetJob.cpp +++ b/launcher/net/NetJob.cpp @@ -144,21 +144,28 @@ void NetJob::updateState() void NetJob::emitFailed(QString reason) { #if defined(LAUNCHER_APPLICATION) - auto response = CustomMessageBox::selectable(nullptr, "Confirm retry", - "The tasks failed\n" - "Failed urls\n" + - getFailedFiles().join("\n\t") + - "\n" - "If this continues to happen please check the logs of the application" - "Do you want to retry?", - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) - ->exec(); - - if (response == QMessageBox::Yes) { - m_try = 0; - executeNextSubTask(); - return; + if (m_ask_retry) { + auto response = CustomMessageBox::selectable(nullptr, "Confirm retry", + "The tasks failed\n" + "Failed urls\n" + + getFailedFiles().join("\n\t") + + "\n" + "If this continues to happen please check the logs of the application" + "Do you want to retry?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response == QMessageBox::Yes) { + m_try = 0; + executeNextSubTask(); + return; + } } #endif ConcurrentTask::emitFailed(reason); -} \ No newline at end of file +} + +void NetJob::setAskRetry(bool askRetry) +{ + m_ask_retry = askRetry; +} diff --git a/launcher/net/NetJob.h b/launcher/net/NetJob.h index 09da957711..b421d24501 100644 --- a/launcher/net/NetJob.h +++ b/launcher/net/NetJob.h @@ -62,6 +62,7 @@ class NetJob : public ConcurrentTask { auto getFailedActions() -> QList; auto getFailedFiles() -> QList; + void setAskRetry(bool askRetry); public slots: // Qt can't handle auto at the start for some reason? @@ -78,4 +79,5 @@ class NetJob : public ConcurrentTask { shared_qobject_ptr m_network; int m_try = 1; + bool m_ask_retry = true; }; From 7a200a337f08cfa1e32102594958f10cb7f000c6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 26 May 2024 11:04:41 +0300 Subject: [PATCH 04/37] update retry netjob dialog Signed-off-by: Trial97 --- launcher/Application.cpp | 1 + launcher/net/ApiDownload.cpp | 1 - launcher/net/ApiUpload.cpp | 1 - launcher/net/NetJob.cpp | 36 +++++++++++-------- launcher/net/NetJob.h | 3 ++ launcher/ui/pages/global/LauncherPage.cpp | 2 ++ launcher/ui/pages/global/LauncherPage.ui | 16 ++++++++- .../ui/widgets/VariableSizedImageObject.cpp | 3 +- 8 files changed, 45 insertions(+), 18 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 96a50f2ba8..06ebf4d71c 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -559,6 +559,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("NumberOfConcurrentTasks", 10); m_settings->registerSetting("NumberOfConcurrentDownloads", 6); + m_settings->registerSetting("NumberOfManualRetries", 1); QString defaultMonospace; int defaultSize = 11; diff --git a/launcher/net/ApiDownload.cpp b/launcher/net/ApiDownload.cpp index 8768b63f86..0494d18ad2 100644 --- a/launcher/net/ApiDownload.cpp +++ b/launcher/net/ApiDownload.cpp @@ -58,7 +58,6 @@ auto ApiDownload::makeFile(QUrl url, QString path, Options options) -> Download: void ApiDownload::init() { - qDebug() << "Setting up api download"; auto api_headers = new ApiHeaderProxy(); addHeaderProxy(api_headers); } diff --git a/launcher/net/ApiUpload.cpp b/launcher/net/ApiUpload.cpp index 505cbd9f99..01b081dd5b 100644 --- a/launcher/net/ApiUpload.cpp +++ b/launcher/net/ApiUpload.cpp @@ -33,7 +33,6 @@ Upload::Ptr ApiUpload::makeByteArray(QUrl url, std::shared_ptr outpu void ApiUpload::init() { - qDebug() << "Setting up api upload"; auto api_headers = new ApiHeaderProxy(); addHeaderProxy(api_headers); } diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp index 65d6ec3a43..639047e436 100644 --- a/launcher/net/NetJob.cpp +++ b/launcher/net/NetJob.cpp @@ -144,21 +144,29 @@ void NetJob::updateState() void NetJob::emitFailed(QString reason) { #if defined(LAUNCHER_APPLICATION) - auto response = CustomMessageBox::selectable(nullptr, "Confirm retry", - "The tasks failed\n" - "Failed urls\n" + - getFailedFiles().join("\n\t") + - "\n" - "If this continues to happen please check the logs of the application" - "Do you want to retry?", - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) - ->exec(); - - if (response == QMessageBox::Yes) { - m_try = 0; - executeNextSubTask(); - return; + if (m_ask_retry || m_manual_try < APPLICATION->settings()->get("NumberOfManualRetries").toInt()) { + m_manual_try++; + auto response = CustomMessageBox::selectable(nullptr, "Confirm retry", + "The tasks failed\n" + "Failed urls\n" + + getFailedFiles().join("\n\t") + + "\n" + "If this continues to happen please check the logs of the application" + "Do you want to retry?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response == QMessageBox::Yes) { + m_try = 0; + executeNextSubTask(); + return; + } } #endif ConcurrentTask::emitFailed(reason); +} + +void NetJob::setAskRetry(bool askRetry) +{ + m_ask_retry = askRetry; } \ No newline at end of file diff --git a/launcher/net/NetJob.h b/launcher/net/NetJob.h index 09da957711..4eaa49df5a 100644 --- a/launcher/net/NetJob.h +++ b/launcher/net/NetJob.h @@ -62,6 +62,7 @@ class NetJob : public ConcurrentTask { auto getFailedActions() -> QList; auto getFailedFiles() -> QList; + void setAskRetry(bool askRetry); public slots: // Qt can't handle auto at the start for some reason? @@ -78,4 +79,6 @@ class NetJob : public ConcurrentTask { shared_qobject_ptr m_network; int m_try = 1; + bool m_ask_retry = true; + int m_manual_try = 0; }; diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 78c44380a0..711b6674c2 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -191,6 +191,7 @@ void LauncherPage::applySettings() s->set("NumberOfConcurrentTasks", ui->numberOfConcurrentTasksSpinBox->value()); s->set("NumberOfConcurrentDownloads", ui->numberOfConcurrentDownloadsSpinBox->value()); + s->set("NumberOfManualRetries", ui->numberOfManualRetriesSpinBox->value()); // Console settings s->set("ShowConsole", ui->showConsoleCheck->isChecked()); @@ -245,6 +246,7 @@ void LauncherPage::loadSettings() ui->numberOfConcurrentTasksSpinBox->setValue(s->get("NumberOfConcurrentTasks").toInt()); ui->numberOfConcurrentDownloadsSpinBox->setValue(s->get("NumberOfConcurrentDownloads").toInt()); + ui->numberOfManualRetriesSpinBox->setValue(s->get("NumberOfManualRetries").toInt()); // Console settings ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool()); diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 928ec81036..8959814bd4 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -7,7 +7,7 @@ 0 0 511 - 629 + 691 @@ -233,6 +233,20 @@ + + + + Number of manual retries + + + + + + + 0 + + + diff --git a/launcher/ui/widgets/VariableSizedImageObject.cpp b/launcher/ui/widgets/VariableSizedImageObject.cpp index 3dd9d5634d..9723a2c568 100644 --- a/launcher/ui/widgets/VariableSizedImageObject.cpp +++ b/launcher/ui/widgets/VariableSizedImageObject.cpp @@ -80,7 +80,7 @@ void VariableSizedImageObject::drawObject(QPainter* painter, { if (!format.hasProperty(ImageData)) { QUrl image_url{ qvariant_cast(format.property(QTextFormat::ImageName)) }; - if (m_fetching_images.contains(image_url)) + if (m_fetching_images.contains(image_url) || image_url.isEmpty()) return; auto meta = std::make_shared(); @@ -140,6 +140,7 @@ void VariableSizedImageObject::loadImage(QTextDocument* doc, std::shared_ptrurl.toEncoded(), QCryptographicHash::Algorithm::Sha1).toHex()))); auto job = new NetJob(QString("Load Image: %1").arg(meta->url.fileName()), APPLICATION->network()); + job->setAskRetry(false); job->addNetAction(Net::ApiDownload::makeCached(meta->url, entry)); auto full_entry_path = entry->getFullPath(); From 694ea654577e920b490769f99926bff6f778d444 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 26 May 2024 11:13:01 +0300 Subject: [PATCH 05/37] disable retry dialog for logo fetching Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourceModel.cpp | 4 +++- launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp | 1 + launcher/ui/pages/modplatform/flame/FlameModel.cpp | 1 + launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp | 1 + launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp | 1 + launcher/ui/pages/modplatform/technic/TechnicModel.cpp | 1 + 6 files changed, 8 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 8a69e910d0..581fbf3b14 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -317,8 +317,10 @@ std::optional ResourceModel::getIcon(QModelIndex& index, const QUrl& url) if (QPixmapCache::find(url.toString(), &pixmap)) return { pixmap }; - if (!m_current_icon_job) + if (!m_current_icon_job) { m_current_icon_job.reset(new NetJob("IconJob", APPLICATION->network())); + m_current_icon_job->setAskRetry(false); + } if (m_currently_running_icon_actions.contains(url)) return {}; diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index d46b97af1a..f116ca9150 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -195,6 +195,7 @@ void ListModel::requestLogo(QString file, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(file)); auto job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network()); + job->setAskRetry(false); job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 3b266bcef9..267c5a3af6 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -110,6 +110,7 @@ void ListModel::requestLogo(QString logo, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo)); auto job = new NetJob(QString("Flame Icon Download %1").arg(logo), APPLICATION->network()); + job->setAskRetry(false); job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index 49666cf6e2..98922123cf 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -264,6 +264,7 @@ void ListModel::requestLogo(QString file) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file)); NetJob* job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network()); + job->setAskRetry(false); job->addNetAction(Net::ApiDownload::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry)); auto fullPath = entry->getFullPath(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index ccfe7eccb3..b53eea4efd 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -254,6 +254,7 @@ void ModpackListModel::requestLogo(QString logo, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry(m_parent->metaEntryBase(), QString("logos/%1").arg(logo)); auto job = new NetJob(QString("%1 Icon Download %2").arg(m_parent->debugName()).arg(logo), APPLICATION->network()); + job->setAskRetry(false); job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index 6f1810d719..4181edab60 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -292,6 +292,7 @@ void Technic::ListModel::requestLogo(QString logo, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("TechnicPacks", QString("logos/%1").arg(logo)); auto job = new NetJob(QString("Technic Icon Download %1").arg(logo), APPLICATION->network()); + job->setAskRetry(false); job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); From 59a8b912746108a1b083ff8a11f7112c23d06433 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 26 May 2024 16:28:07 +0300 Subject: [PATCH 06/37] add spacing to retry modal Signed-off-by: Trial97 --- launcher/net/NetJob.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp index 639047e436..66054cc8f3 100644 --- a/launcher/net/NetJob.cpp +++ b/launcher/net/NetJob.cpp @@ -147,11 +147,11 @@ void NetJob::emitFailed(QString reason) if (m_ask_retry || m_manual_try < APPLICATION->settings()->get("NumberOfManualRetries").toInt()) { m_manual_try++; auto response = CustomMessageBox::selectable(nullptr, "Confirm retry", - "The tasks failed\n" + "The tasks failed.\n" "Failed urls\n" + getFailedFiles().join("\n\t") + - "\n" - "If this continues to happen please check the logs of the application" + ".\n" + "If this continues to happen please check the logs of the application.\n" "Do you want to retry?", QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); From e94243f99bc6840ec85430d3bcb72e748154e4f4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 30 May 2024 09:56:55 +0300 Subject: [PATCH 07/37] fix blocked mods api Signed-off-by: Trial97 --- launcher/modplatform/flame/FileResolvingTask.cpp | 1 + launcher/net/NetJob.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 8d23896d9e..3f96858926 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -74,6 +74,7 @@ void Flame::FileResolvingTask::netJobFinished() setProgress(1, 3); // job to check modrinth for blocked projects m_checkJob.reset(new NetJob("Modrinth check", m_network)); + m_checkJob->setAskRetry(false); blockedProjects = QMap>(); QJsonDocument doc; diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp index 66054cc8f3..62c9d42966 100644 --- a/launcher/net/NetJob.cpp +++ b/launcher/net/NetJob.cpp @@ -144,7 +144,7 @@ void NetJob::updateState() void NetJob::emitFailed(QString reason) { #if defined(LAUNCHER_APPLICATION) - if (m_ask_retry || m_manual_try < APPLICATION->settings()->get("NumberOfManualRetries").toInt()) { + if (m_ask_retry && m_manual_try < APPLICATION->settings()->get("NumberOfManualRetries").toInt()) { m_manual_try++; auto response = CustomMessageBox::selectable(nullptr, "Confirm retry", "The tasks failed.\n" From d2510b851ba9576304f89c7e146bbd41215542a6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jun 2024 22:45:15 +0300 Subject: [PATCH 08/37] mark files as duplicate Signed-off-by: Trial97 --- launcher/FileSystem.cpp | 26 +++++++++++++++++++ launcher/FileSystem.h | 2 ++ launcher/minecraft/mod/Resource.cpp | 7 +++-- .../minecraft/mod/tasks/BasicFolderLoadTask.h | 17 ++++++------ .../minecraft/mod/tasks/ModFolderLoadTask.cpp | 13 +++++----- 5 files changed, 49 insertions(+), 16 deletions(-) diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index cafc4f25ab..36410f03e8 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -1701,4 +1701,30 @@ QString getPathNameInLocal8bit(const QString& file) } #endif +QString getUniqueResourceName(const QString& filePath) +{ + auto newFileName = filePath; + if (!newFileName.endsWith(".disabled")) { + return newFileName; // prioritize enabled mods + } + newFileName.chop(9); + if (!QFile::exists(newFileName)) { + return filePath; + } + QFileInfo fileInfo(filePath); + auto baseName = fileInfo.completeBaseName(); + auto path = fileInfo.absolutePath(); + + int counter = 1; + do { + if (counter == 1) { + newFileName = FS::PathCombine(path, baseName + ".duplicate"); + } else { + newFileName = FS::PathCombine(path, baseName + ".duplicate" + QString::number(counter)); + } + counter++; + } while (QFile::exists(newFileName)); + + return newFileName; +} } // namespace FS diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index 23bf5f16eb..66adf7a36f 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -560,4 +560,6 @@ uintmax_t hardLinkCount(const QString& path); QString getPathNameInLocal8bit(const QString& file); #endif +QString getUniqueResourceName(const QString& filePath); + } // namespace FS diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index 62bf6b9a23..6066f02dbb 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -161,10 +161,13 @@ bool Resource::enable(EnableAction action) path.chop(9); } else { path += ".disabled"; + auto newFilePath = FS::getUniqueResourceName(path); + if (newFilePath != path) { + FS::move(path, newFilePath); + } } if (QFileInfo::exists(path)) { // the path exists so just remove the file at path - if (!QFile::remove(path)) - return false; + return false; } if (!file.rename(path)) return false; diff --git a/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h b/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h index 6e8b8ed43c..2bce2c137a 100644 --- a/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h @@ -7,6 +7,7 @@ #include +#include "FileSystem.h" #include "minecraft/mod/Resource.h" #include "tasks/Task.h" @@ -49,16 +50,16 @@ class BasicFolderLoadTask : public Task { connect(this, &Task::finished, this->thread(), &QThread::quit); m_dir.refresh(); - QStringList names; for (auto entry : m_dir.entryInfoList()) { - auto resource = m_create_func(entry); - if (names.contains(resource->name())) { - resource->destroy(); - } else { - names << resource->name(); - resource->moveToThread(m_thread_to_spawn_into); - m_result->resources.insert(resource->internal_id(), resource); + auto filePath = entry.absoluteFilePath(); + auto newFilePath = FS::getUniqueResourceName(filePath); + if (newFilePath != filePath) { + FS::move(filePath, newFilePath); + entry = QFileInfo(newFilePath); } + auto resource = m_create_func(entry); + resource->moveToThread(m_thread_to_spawn_into); + m_result->resources.insert(resource->internal_id(), resource); } if (m_aborted) diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index c11759dd2f..501d5be134 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -36,6 +36,7 @@ #include "ModFolderLoadTask.h" +#include "FileSystem.h" #include "minecraft/mod/MetadataHandler.h" #include @@ -62,15 +63,15 @@ void ModFolderLoadTask::executeTask() // Read JAR files that don't have metadata m_mods_dir.refresh(); - QStringList names; for (auto entry : m_mods_dir.entryInfoList()) { + auto filePath = entry.absoluteFilePath(); + auto newFilePath = FS::getUniqueResourceName(filePath); + if (newFilePath != filePath) { + FS::move(filePath, newFilePath); + entry = QFileInfo(newFilePath); + } Mod* mod(new Mod(entry)); - if (names.contains(mod->name())) { - mod->destroy(m_index_dir, true); - continue; - } - names << mod->name(); if (mod->enabled()) { if (m_result->mods.contains(mod->internal_id())) { m_result->mods[mod->internal_id()]->setStatus(ModStatus::Installed); From b872f88617fa282f0b1a23e0a134225d360a000c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jun 2024 22:46:39 +0300 Subject: [PATCH 09/37] do not double rename Signed-off-by: Trial97 --- launcher/minecraft/mod/Resource.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index 6066f02dbb..9228d5165f 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -161,10 +161,7 @@ bool Resource::enable(EnableAction action) path.chop(9); } else { path += ".disabled"; - auto newFilePath = FS::getUniqueResourceName(path); - if (newFilePath != path) { - FS::move(path, newFilePath); - } + path = FS::getUniqueResourceName(path); } if (QFileInfo::exists(path)) { // the path exists so just remove the file at path return false; From 1a84dc9bcabbd212d1402d04f3f8a41021bdca8f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jun 2024 22:47:42 +0300 Subject: [PATCH 10/37] no need for extra exist check Signed-off-by: Trial97 --- launcher/minecraft/mod/Resource.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index 9228d5165f..62871cbf25 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -163,9 +163,6 @@ bool Resource::enable(EnableAction action) path += ".disabled"; path = FS::getUniqueResourceName(path); } - if (QFileInfo::exists(path)) { // the path exists so just remove the file at path - return false; - } if (!file.rename(path)) return false; From 8cdaf5d05f714fadc899081a1100f594f0e19782 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jun 2024 23:27:27 +0300 Subject: [PATCH 11/37] fix tests Signed-off-by: Trial97 --- launcher/minecraft/mod/Resource.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index 62871cbf25..2a76269534 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -161,7 +161,9 @@ bool Resource::enable(EnableAction action) path.chop(9); } else { path += ".disabled"; - path = FS::getUniqueResourceName(path); + if (QFile::exists(path)) { + path = FS::getUniqueResourceName(path); + } } if (!file.rename(path)) return false; From bb48d1ec9d4aa023080c43811c91c8959f453b7b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 24 Jun 2024 00:29:21 +0300 Subject: [PATCH 12/37] made sure that the retry dialog is not displayed offline Signed-off-by: Trial97 --- launcher/net/NetJob.cpp | 15 ++++++++++++++- launcher/net/NetJob.h | 1 + launcher/news/NewsChecker.cpp | 1 + launcher/translations/TranslationsModel.cpp | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp index 074d58aa9d..8265a63ded 100644 --- a/launcher/net/NetJob.cpp +++ b/launcher/net/NetJob.cpp @@ -36,6 +36,7 @@ */ #include "NetJob.h" +#include #include "net/NetRequest.h" #include "tasks/ConcurrentTask.h" #if defined(LAUNCHER_APPLICATION) @@ -145,10 +146,22 @@ void NetJob::updateState() .arg(QString::number(m_doing.count()), QString::number(m_done.count()), QString::number(totalSize()))); } +bool NetJob::isOnline() +{ + // check some errors that are ussually associated with the lack of internet + for (auto job : getFailedActions()) { + auto err = job->error(); + if (err != QNetworkReply::HostNotFoundError && err != QNetworkReply::NetworkSessionFailedError) { + return true; + } + } + return false; +}; + void NetJob::emitFailed(QString reason) { #if defined(LAUNCHER_APPLICATION) - if (m_ask_retry && m_manual_try < APPLICATION->settings()->get("NumberOfManualRetries").toInt()) { + if (m_ask_retry && m_manual_try < APPLICATION->settings()->get("NumberOfManualRetries").toInt() && isOnline()) { m_manual_try++; auto response = CustomMessageBox::selectable(nullptr, "Confirm retry", "The tasks failed.\n" diff --git a/launcher/net/NetJob.h b/launcher/net/NetJob.h index 9d617b2098..59213ba152 100644 --- a/launcher/net/NetJob.h +++ b/launcher/net/NetJob.h @@ -74,6 +74,7 @@ class NetJob : public ConcurrentTask { protected: void updateState() override; + bool isOnline(); private: shared_qobject_ptr m_network; diff --git a/launcher/news/NewsChecker.cpp b/launcher/news/NewsChecker.cpp index 33fb7eceb8..169589f783 100644 --- a/launcher/news/NewsChecker.cpp +++ b/launcher/news/NewsChecker.cpp @@ -58,6 +58,7 @@ void NewsChecker::reloadNews() NetJob::Ptr job{ new NetJob("News RSS Feed", m_network) }; job->addNetAction(Net::Download::makeByteArray(m_feedUrl, newsData)); + job->setAskRetry(false); QObject::connect(job.get(), &NetJob::succeeded, this, &NewsChecker::rssDownloadFinished); QObject::connect(job.get(), &NetJob::failed, this, &NewsChecker::rssDownloadFailed); m_newsNetJob.reset(job); diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 56ade8e323..016428d1c9 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -553,6 +553,7 @@ void TranslationsModel::downloadIndex() auto task = Net::Download::makeCached(QUrl(BuildConfig.TRANSLATIONS_BASE_URL + "index_v2.json"), entry); d->m_index_task = task.get(); d->m_index_job->addNetAction(task); + d->m_index_job->setAskRetry(false); connect(d->m_index_job.get(), &NetJob::failed, this, &TranslationsModel::indexFailed); connect(d->m_index_job.get(), &NetJob::succeeded, this, &TranslationsModel::indexReceived); d->m_index_job->start(); From e57c2180da6be232e0c1710bb4aa3060011a85da Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 24 Jun 2024 03:06:10 +0300 Subject: [PATCH 13/37] Resolve issue with multiple loaders during update Signed-off-by: Trial97 --- launcher/minecraft/PackProfile.cpp | 21 +- launcher/minecraft/PackProfile.h | 1 + launcher/modplatform/CheckUpdateTask.h | 10 +- launcher/modplatform/flame/FlameAPI.cpp | 41 ++- launcher/modplatform/flame/FlameAPI.h | 21 +- .../modplatform/flame/FlameCheckUpdate.cpp | 23 +- launcher/modplatform/flame/FlameCheckUpdate.h | 4 +- .../modrinth/ModrinthCheckUpdate.cpp | 276 ++++++++++-------- .../modrinth/ModrinthCheckUpdate.h | 15 +- launcher/ui/dialogs/ModUpdateDialog.cpp | 13 +- 10 files changed, 265 insertions(+), 160 deletions(-) diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index 4b17cdf070..fb866ede15 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -58,7 +58,6 @@ #include "ComponentUpdateTask.h" #include "PackProfile.h" #include "PackProfile_p.h" -#include "minecraft/mod/Mod.h" #include "modplatform/ModIndex.h" static const QMap modloaderMapping{ { "net.neoforged", ModPlatform::NeoForge }, @@ -1022,3 +1021,23 @@ std::optional PackProfile::getSupportedModLoaders() loaders |= ModPlatform::Forge; return loaders; } + +QList PackProfile::getModLoadersList() +{ + QList result; + for (auto c : d->components) { + if (c->isEnabled() && modloaderMapping.contains(c->getID())) { + result.append(modloaderMapping[c->getID()]); + } + } + + // TODO: remove this or add version condition once Quilt drops official Fabric support + if (result.contains(ModPlatform::Quilt) && !result.contains(ModPlatform::Fabric)) { + result.append(ModPlatform::Fabric); + } + if (getComponentVersion("net.minecraft") == "1.20.1" && result.contains(ModPlatform::NeoForge) && + !result.contains(ModPlatform::Forge)) { + result.append(ModPlatform::Forge); + } + return result; +} diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h index e58e9ae9a5..9b6710cc3a 100644 --- a/launcher/minecraft/PackProfile.h +++ b/launcher/minecraft/PackProfile.h @@ -146,6 +146,7 @@ class PackProfile : public QAbstractListModel { std::optional getModLoaders(); // this returns aditional loaders(Quilt supports fabric and NeoForge supports Forge) std::optional getSupportedModLoaders(); + QList getModLoadersList(); private: void scheduleSave(); diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index b19b254842..fecb842fd3 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -3,7 +3,6 @@ #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; @@ -16,8 +15,14 @@ class CheckUpdateTask : public Task { CheckUpdateTask(QList& mods, std::list& mcVersions, std::optional loaders, + QList loadersList, std::shared_ptr mods_folder) - : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder){}; + : Task(nullptr) + , m_mods(mods) + , m_game_versions(mcVersions) + , m_loaders(loaders) + , m_loaders_list(loadersList) + , m_mods_folder(mods_folder){}; struct UpdatableMod { QString name; @@ -68,6 +73,7 @@ class CheckUpdateTask : public Task { QList& m_mods; std::list& m_game_versions; std::optional m_loaders; + QList m_loaders_list; std::shared_ptr m_mods_folder; std::vector m_updatable; diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index a1cfe1a60e..72437976df 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -4,6 +4,7 @@ #include "FlameAPI.h" #include +#include #include "FlameModIndex.h" #include "Application.h" @@ -12,7 +13,6 @@ #include "net/ApiDownload.h" #include "net/ApiUpload.h" #include "net/NetJob.h" -#include "net/Upload.h" Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, std::shared_ptr response) { @@ -34,7 +34,7 @@ Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, std::shar return netJob; } -auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString +QString FlameAPI::getModFileChangelog(int modId, int fileId) { QEventLoop lock; QString changelog; @@ -69,7 +69,7 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString return changelog; } -auto FlameAPI::getModDescription(int modId) -> QString +QString FlameAPI::getModDescription(int modId) { QEventLoop lock; QString description; @@ -102,7 +102,7 @@ auto FlameAPI::getModDescription(int modId) -> QString return description; } -auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::IndexedVersion +QList FlameAPI::getLatestVersions(VersionSearchArgs&& args) { auto versions_url_optional = getVersionsURL(args); if (!versions_url_optional.has_value()) @@ -114,7 +114,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe auto netJob = makeShared(QString("Flame::GetLatestVersion(%1)").arg(args.pack.name), APPLICATION->network()); auto response = std::make_shared(); - ModPlatform::IndexedVersion ver; + QList ver; netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response)); @@ -134,9 +134,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe for (auto file : arr) { auto file_obj = Json::requireObject(file); - auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); - if (file_tmp.date > ver.date && (!args.loaders.has_value() || !file_tmp.loaders || args.loaders.value() & file_tmp.loaders)) - ver = file_tmp; + ver.append(FlameMod::loadIndexedPackVersion(file_obj)); } } catch (Json::JsonException& e) { @@ -146,7 +144,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe } }); - QObject::connect(netJob.get(), &NetJob::finished, [&loop] { loop.quit(); }); + QObject::connect(netJob.get(), &NetJob::finished, &loop, &QEventLoop::quit); netJob->start(); @@ -260,4 +258,27 @@ QList FlameAPI::loadModCategories(std::shared_ptr FlameAPI::getLatestVersion(QList versions, + QList instanceLoaders, + ModPlatform::ModLoaderTypes modLoaders) +{ + // edge case: mod has installed for forge but the instance is fabric => fabric version will be prioritizated on update + auto bestVersion = [&versions](ModPlatform::ModLoaderTypes loader) { + std::optional ver; + for (auto file_tmp : versions) { + if (file_tmp.loaders & loader && (!ver.has_value() || file_tmp.date > ver->date)) { + ver = file_tmp; + } + } + return ver; + }; + for (auto l : instanceLoaders) { + auto ver = bestVersion(l); + if (ver.has_value()) { + return ver; + } + } + return bestVersion(modLoaders); +} diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index dfe76f9d5b..1160151c51 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include #include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" @@ -13,10 +12,13 @@ class FlameAPI : public NetworkResourceAPI { public: - auto getModFileChangelog(int modId, int fileId) -> QString; - auto getModDescription(int modId) -> QString; + QString getModFileChangelog(int modId, int fileId); + QString getModDescription(int modId); - auto getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::IndexedVersion; + QList getLatestVersions(VersionSearchArgs&& args); + std::optional getLatestVersion(QList versions, + QList instanceLoaders, + ModPlatform::ModLoaderTypes fallback); Task::Ptr getProjects(QStringList addonIds, std::shared_ptr response) const override; Task::Ptr matchFingerprints(const QList& fingerprints, std::shared_ptr response); @@ -26,9 +28,9 @@ class FlameAPI : public NetworkResourceAPI { static Task::Ptr getModCategories(std::shared_ptr response); static QList loadModCategories(std::shared_ptr response); - [[nodiscard]] auto getSortingMethods() const -> QList override; + [[nodiscard]] QList getSortingMethods() const override; - static inline auto validateModLoaders(ModPlatform::ModLoaderTypes loaders) -> bool + static inline bool validateModLoaders(ModPlatform::ModLoaderTypes loaders) { return loaders & (ModPlatform::NeoForge | ModPlatform::Forge | ModPlatform::Fabric | ModPlatform::Quilt); } @@ -67,7 +69,7 @@ class FlameAPI : public NetworkResourceAPI { return 0; } - static auto getModLoaderStrings(const ModPlatform::ModLoaderTypes types) -> const QStringList + static const QStringList getModLoaderStrings(const ModPlatform::ModLoaderTypes types) { QStringList l; for (auto loader : { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Fabric, ModPlatform::Quilt }) { @@ -78,10 +80,7 @@ class FlameAPI : public NetworkResourceAPI { return l; } - static auto getModLoaderFilters(ModPlatform::ModLoaderTypes types) -> const QString - { - return "[" + getModLoaderStrings(types).join(',') + "]"; - } + static const QString getModLoaderFilters(ModPlatform::ModLoaderTypes types) { return "[" + getModLoaderStrings(types).join(',') + "]"; } private: [[nodiscard]] std::optional getSearchURL(SearchArgs const& args) const override diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index b4eb304f02..9deffce545 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -132,25 +132,26 @@ void FlameCheckUpdate::executeTask() setStatus(tr("Getting API response from CurseForge for '%1'...").arg(mod->name())); setProgress(i++, m_mods.size()); - auto latest_ver = api.getLatestVersion({ { mod->metadata()->project_id.toString() }, m_game_versions, m_loaders }); + auto latest_vers = api.getLatestVersions({ { mod->metadata()->project_id.toString() }, m_game_versions, m_loaders }); // Check if we were aborted while getting the latest version if (m_was_aborted) { aborted(); return; } + auto latest_ver = api.getLatestVersion(latest_vers, m_loaders_list, mod->loaders()); setStatus(tr("Parsing the API response from CurseForge for '%1'...").arg(mod->name())); - if (!latest_ver.addonId.isValid()) { + if (!latest_ver.has_value() || !latest_ver->addonId.isValid()) { emit checkFailed(mod, tr("No valid version found for this mod. It's probably unavailable for the current game " "version / mod loader.")); continue; } - if (latest_ver.downloadUrl.isEmpty() && latest_ver.fileId != mod->metadata()->file_id) { - auto pack = getProjectInfo(latest_ver); - auto recover_url = QString("%1/download/%2").arg(pack.websiteUrl, latest_ver.fileId.toString()); + if (latest_ver->downloadUrl.isEmpty() && latest_ver->fileId != mod->metadata()->file_id) { + auto pack = getProjectInfo(latest_ver.value()); + auto recover_url = QString("%1/download/%2").arg(pack.websiteUrl, latest_ver->fileId.toString()); emit checkFailed(mod, tr("Mod has a new update available, but is not downloadable using CurseForge."), recover_url); continue; @@ -166,19 +167,19 @@ void FlameCheckUpdate::executeTask() pack->authors.append({ author }); pack->description = mod->description(); pack->provider = ModPlatform::ResourceProvider::FLAME; - if (!latest_ver.hash.isEmpty() && (mod->metadata()->hash != latest_ver.hash || mod->status() == ModStatus::NotInstalled)) { + if (!latest_ver->hash.isEmpty() && (mod->metadata()->hash != latest_ver->hash || mod->status() == ModStatus::NotInstalled)) { auto old_version = mod->version(); if (old_version.isEmpty() && mod->status() != ModStatus::NotInstalled) { - auto current_ver = getFileInfo(latest_ver.addonId.toInt(), mod->metadata()->file_id.toInt()); + auto current_ver = getFileInfo(latest_ver->addonId.toInt(), mod->metadata()->file_id.toInt()); old_version = current_ver.version; } - auto download_task = makeShared(pack, latest_ver, m_mods_folder); - m_updatable.emplace_back(pack->name, mod->metadata()->hash, old_version, latest_ver.version, latest_ver.version_type, - api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()), + auto download_task = makeShared(pack, latest_ver.value(), m_mods_folder); + m_updatable.emplace_back(pack->name, mod->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); } - m_deps.append(std::make_shared(pack, latest_ver)); + m_deps.append(std::make_shared(pack, latest_ver.value())); } emitSucceeded(); diff --git a/launcher/modplatform/flame/FlameCheckUpdate.h b/launcher/modplatform/flame/FlameCheckUpdate.h index f5bb1653d5..bd6806c607 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.h +++ b/launcher/modplatform/flame/FlameCheckUpdate.h @@ -1,6 +1,5 @@ #pragma once -#include "Application.h" #include "modplatform/CheckUpdateTask.h" #include "net/NetJob.h" @@ -11,8 +10,9 @@ class FlameCheckUpdate : public CheckUpdateTask { FlameCheckUpdate(QList& mods, std::list& mcVersions, std::optional loaders, + QList loadersList, std::shared_ptr mods_folder) - : CheckUpdateTask(mods, mcVersions, loaders, mods_folder) + : CheckUpdateTask(mods, mcVersions, loaders, loadersList, mods_folder) {} public slots: diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 700bcd2e60..50fb11f059 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -1,23 +1,32 @@ #include "ModrinthCheckUpdate.h" +#include "Application.h" #include "ModrinthAPI.h" #include "ModrinthPackIndex.h" #include "Json.h" +#include "QObjectPtr.h" #include "ResourceDownloadTask.h" #include "modplatform/helpers/HashUtils.h" #include "tasks/ConcurrentTask.h" -#include "minecraft/mod/ModFolderModel.h" - static ModrinthAPI api; +ModrinthCheckUpdate::ModrinthCheckUpdate(QList& mods, + std::list& mcVersions, + std::optional loaders, + QList loadersList, + std::shared_ptr mods_folder) + : CheckUpdateTask(mods, mcVersions, loaders, loadersList, mods_folder) + , m_hash_type(ModPlatform::ProviderCapabilities::hashType(ModPlatform::ResourceProvider::MODRINTH).first()) +{} + bool ModrinthCheckUpdate::abort() { - if (m_net_job) - return m_net_job->abort(); + if (m_job) + return m_job->abort(); return true; } @@ -29,15 +38,10 @@ bool ModrinthCheckUpdate::abort() void ModrinthCheckUpdate::executeTask() { setStatus(tr("Preparing mods for Modrinth...")); - setProgress(0, 3); - - QHash mappings; + setProgress(0, 9); - // Create all hashes - QStringList hashes; - auto best_hash_type = ModPlatform::ProviderCapabilities::hashType(ModPlatform::ResourceProvider::MODRINTH).first(); - - ConcurrentTask hashing_task(this, "MakeModrinthHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); + auto hashing_task = + makeShared(this, "MakeModrinthHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); for (auto* mod : m_mods) { if (!mod->enabled()) { emit checkFailed(mod, tr("Disabled mods won't be updated, to prevent mod duplication issues!")); @@ -49,132 +53,176 @@ 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 (mod->metadata()->hash_format != best_hash_type) { + if (mod->metadata()->hash_format != m_hash_type) { auto hash_task = Hashing::createHasher(mod->fileinfo().absoluteFilePath(), ModPlatform::ResourceProvider::MODRINTH); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [&hashes, &mappings, mod](QString hash) { - hashes.append(hash); - mappings.insert(hash, mod); - }); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mappings.insert(hash, mod); }); connect(hash_task.get(), &Task::failed, [this] { failed("Failed to generate hash"); }); - hashing_task.addTask(hash_task); + hashing_task->addTask(hash_task); } else { - hashes.append(hash); - mappings.insert(hash, mod); + m_mappings.insert(hash, mod); } } - QEventLoop loop; - connect(&hashing_task, &Task::finished, [&loop] { loop.quit(); }); - hashing_task.start(); - loop.exec(); - - auto response = std::make_shared(); - auto job = api.latestVersions(hashes, best_hash_type, m_game_versions, m_loaders, response); - - connect(job.get(), &Task::succeeded, this, [this, response, mappings, best_hash_type, job] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from ModrinthCheckUpdate at " << parse_error.offset - << " reason: " << parse_error.errorString(); - qWarning() << *response; - - emitFailed(parse_error.errorString()); - return; - } + connect(hashing_task.get(), &Task::finished, this, &ModrinthCheckUpdate::checkNextLoader); + m_job = hashing_task; + hashing_task->start(); +} - setStatus(tr("Parsing the API response from Modrinth...")); - setProgress(2, 3); +void ModrinthCheckUpdate::checkVersionsResponse(std::shared_ptr response, + ModPlatform::ModLoaderTypes loader, + bool forceModLoaderCheck) +{ + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from ModrinthCheckUpdate at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + + emitFailed(parse_error.errorString()); + return; + } - try { - for (auto hash : mappings.keys()) { - auto project_obj = doc[hash].toObject(); + setStatus(tr("Parsing the API response from Modrinth...")); + setProgress(m_next_loader_idx * 2, 9); - // If the returned project is empty, but we have Modrinth metadata, - // it means this specific version is not available - if (project_obj.isEmpty()) { - qDebug() << "Mod " << mappings.find(hash).value()->name() << " got an empty response."; - qDebug() << "Hash: " << hash; + try { + for (auto hash : m_mappings.keys()) { + if (forceModLoaderCheck && !m_mappings[hash]->loaders().testAnyFlags(loader)) { + continue; + } + auto project_obj = doc[hash].toObject(); - emit checkFailed( - mappings.find(hash).value(), - tr("No valid version found for this mod. It's probably unavailable for the current game version / mod loader.")); + // If the returned project is empty, but we have Modrinth metadata, + // it means this specific version is not available + if (project_obj.isEmpty()) { + qDebug() << "Mod " << m_mappings.find(hash).value()->name() << " got an empty response." + << "Hash: " << hash; - continue; - } + continue; + } - // Sometimes a version may have multiple files, one with "forge" and one with "fabric", - // so we may want to filter it - QString loader_filter; - if (m_loaders.has_value()) { - static auto flags = { ModPlatform::ModLoaderType::NeoForge, ModPlatform::ModLoaderType::Forge, - ModPlatform::ModLoaderType::Fabric, ModPlatform::ModLoaderType::Quilt }; - for (auto flag : flags) { - if (m_loaders.value().testFlag(flag)) { - loader_filter = ModPlatform::getModLoaderAsString(flag); - break; - } - } + // Sometimes a version may have multiple files, one with "forge" and one with "fabric", + // so we may want to filter it + QString loader_filter; + static auto flags = { ModPlatform::ModLoaderType::NeoForge, ModPlatform::ModLoaderType::Forge, + ModPlatform::ModLoaderType::Quilt, ModPlatform::ModLoaderType::Fabric }; + for (auto flag : flags) { + if (loader.testFlag(flag)) { + loader_filter = ModPlatform::getModLoaderAsString(flag); + break; } + } - // Currently, we rely on a couple heuristics to determine whether an update is actually available or not: - // - The file needs to be preferred: It is either the primary file, or the one found via (explicit) usage of the - // loader_filter - // - 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 .-. + // Currently, we rely on a couple heuristics to determine whether an update is actually available or not: + // - The file needs to be preferred: It is either the primary file, or the one found via (explicit) usage of the + // loader_filter + // - 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, best_hash_type, loader_filter); - if (project_ver.downloadUrl.isEmpty()) { - qCritical() << "Modrinth mod without download url!"; - qCritical() << project_ver.fileName; + auto project_ver = Modrinth::loadIndexedPackVersion(project_obj, m_hash_type, loader_filter); + if (project_ver.downloadUrl.isEmpty()) { + qCritical() << "Modrinth mod without download url!" << project_ver.fileName; - emit checkFailed(mappings.find(hash).value(), tr("Mod has an empty download URL")); + continue; + } + auto mod_iter = m_mappings.find(hash); + if (mod_iter == m_mappings.end()) { + qCritical() << "Failed to remap mod from Modrinth!"; + continue; + } + auto mod = *mod_iter; + m_mappings.remove(hash); + + auto key = project_ver.hash; + + // Fake pack with the necessary info to pass to the download task :) + auto pack = std::make_shared(); + pack->name = mod->name(); + pack->slug = mod->metadata()->slug; + pack->addonId = mod->metadata()->project_id; + pack->websiteUrl = mod->homeurl(); + for (auto& author : mod->authors()) + pack->authors.append({ author }); + pack->description = mod->description(); + pack->provider = ModPlatform::ResourceProvider::MODRINTH; + if ((key != hash && project_ver.is_preferred) || (mod->status() == ModStatus::NotInstalled)) { + if (mod->version() == project_ver.version_number) continue; - } - auto mod_iter = mappings.find(hash); - if (mod_iter == mappings.end()) { - qCritical() << "Failed to remap mod from Modrinth!"; - continue; - } - auto mod = *mod_iter; - - auto key = project_ver.hash; - - // Fake pack with the necessary info to pass to the download task :) - auto pack = std::make_shared(); - pack->name = mod->name(); - pack->slug = mod->metadata()->slug; - pack->addonId = mod->metadata()->project_id; - pack->websiteUrl = mod->homeurl(); - for (auto& author : mod->authors()) - pack->authors.append({ author }); - pack->description = mod->description(); - pack->provider = ModPlatform::ResourceProvider::MODRINTH; - if ((key != hash && project_ver.is_preferred) || (mod->status() == ModStatus::NotInstalled)) { - if (mod->version() == project_ver.version_number) - continue; - - auto download_task = makeShared(pack, project_ver, m_mods_folder); - - m_updatable.emplace_back(pack->name, hash, mod->version(), project_ver.version_number, project_ver.version_type, - project_ver.changelog, ModPlatform::ResourceProvider::MODRINTH, download_task); - } - m_deps.append(std::make_shared(pack, project_ver)); + auto download_task = makeShared(pack, project_ver, m_mods_folder); + + m_updatable.emplace_back(pack->name, hash, mod->version(), project_ver.version_number, project_ver.version_type, + project_ver.changelog, ModPlatform::ResourceProvider::MODRINTH, download_task); } - } catch (Json::JsonException& e) { - emitFailed(e.cause() + " : " + e.what()); - return; + m_deps.append(std::make_shared(pack, project_ver)); } - emitSucceeded(); - }); + } catch (Json::JsonException& e) { + emitFailed(e.cause() + " : " + e.what()); + return; + } + checkNextLoader(); +} + +void ModrinthCheckUpdate::getUpdateModsForLoader(ModPlatform::ModLoaderTypes loader, bool forceModLoaderCheck) +{ + auto response = std::make_shared(); + QStringList hashes; + if (forceModLoaderCheck) { + for (auto hash : m_mappings.keys()) { + if (m_mappings[hash]->loaders().testAnyFlags(loader)) { + hashes.append(hash); + } + } + } else { + hashes = m_mappings.keys(); + } + auto job = api.latestVersions(hashes, m_hash_type, m_game_versions, loader, response); + + connect(job.get(), &Task::succeeded, this, + [this, response, loader, forceModLoaderCheck] { checkVersionsResponse(response, loader, forceModLoaderCheck); }); - connect(job.get(), &Task::failed, this, &ModrinthCheckUpdate::emitFailed); + connect(job.get(), &Task::failed, this, &ModrinthCheckUpdate::checkNextLoader); setStatus(tr("Waiting for the API response from Modrinth...")); - setProgress(1, 3); + setProgress(m_next_loader_idx * 2 - 1, 9); - m_net_job = qSharedPointerObjectCast(job); + m_job = job; job->start(); } + +void ModrinthCheckUpdate::checkNextLoader() +{ + if (m_mappings.isEmpty()) { + emitSucceeded(); + return; + } + if (m_next_loader_idx < m_loaders_list.size()) { + getUpdateModsForLoader(m_loaders_list.at(m_next_loader_idx)); + m_next_loader_idx++; + return; + } + static auto flags = { ModPlatform::ModLoaderType::NeoForge, ModPlatform::ModLoaderType::Forge, ModPlatform::ModLoaderType::Quilt, + ModPlatform::ModLoaderType::Fabric }; + for (auto flag : flags) { + if (!m_loaders_list.contains(flag)) { + m_loaders_list.append(flag); + m_next_loader_idx++; + setProgress(m_next_loader_idx * 2 - 1, 9); + for (auto m : m_mappings) { + if (m->loaders().testAnyFlag(flag)) { + getUpdateModsForLoader(flag, true); + return; + } + } + setProgress(m_next_loader_idx * 2, 9); + } + } + for (auto m : m_mappings) { + emit checkFailed(m, + tr("No valid version found for this mod. It's probably unavailable for the current game version / mod loader.")); + } + emitSucceeded(); + return; +} diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h index f2f2c7e92c..2abd51970c 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h @@ -1,8 +1,6 @@ #pragma once -#include "Application.h" #include "modplatform/CheckUpdateTask.h" -#include "net/NetJob.h" class ModrinthCheckUpdate : public CheckUpdateTask { Q_OBJECT @@ -11,16 +9,21 @@ class ModrinthCheckUpdate : public CheckUpdateTask { ModrinthCheckUpdate(QList& mods, std::list& mcVersions, std::optional loaders, - std::shared_ptr mods_folder) - : CheckUpdateTask(mods, mcVersions, loaders, mods_folder) - {} + QList loadersList, + std::shared_ptr mods_folder); public slots: bool abort() override; protected slots: void executeTask() override; + void getUpdateModsForLoader(ModPlatform::ModLoaderTypes loader, bool forceModLoaderCheck = false); + void checkVersionsResponse(std::shared_ptr response, ModPlatform::ModLoaderTypes loader, bool forceModLoaderCheck = false); + void checkNextLoader(); private: - NetJob::Ptr m_net_job = nullptr; + Task::Ptr m_job = nullptr; + QHash m_mappings; + QString m_hash_type; + int m_next_loader_idx = 0; }; diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 1583b4f463..5cb25b218a 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -1,4 +1,5 @@ #include "ModUpdateDialog.h" +#include "Application.h" #include "ChooseProviderDialog.h" #include "CustomMessageBox.h" #include "ProgressDialog.h" @@ -32,7 +33,12 @@ static std::list mcVersions(BaseInstance* inst) static std::optional mcLoaders(BaseInstance* inst) { - return { static_cast(inst)->getPackProfile()->getSupportedModLoaders() }; + return static_cast(inst)->getPackProfile()->getSupportedModLoaders(); +} + +static QList mcLoadersList(BaseInstance* inst) +{ + return static_cast(inst)->getPackProfile()->getModLoadersList(); } ModUpdateDialog::ModUpdateDialog(QWidget* parent, @@ -87,11 +93,12 @@ void ModUpdateDialog::checkCandidates() auto versions = mcVersions(m_instance); auto loaders = mcLoaders(m_instance); + auto loadersList = mcLoadersList(m_instance); SequentialTask check_task(m_parent, tr("Checking for updates")); if (!m_modrinth_to_update.empty()) { - m_modrinth_check_task.reset(new ModrinthCheckUpdate(m_modrinth_to_update, versions, loaders, m_mod_model)); + m_modrinth_check_task.reset(new ModrinthCheckUpdate(m_modrinth_to_update, versions, loaders, loadersList, m_mod_model)); connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({ mod, reason, recover_url }); }); @@ -99,7 +106,7 @@ void ModUpdateDialog::checkCandidates() } if (!m_flame_to_update.empty()) { - m_flame_check_task.reset(new FlameCheckUpdate(m_flame_to_update, versions, loaders, m_mod_model)); + m_flame_check_task.reset(new FlameCheckUpdate(m_flame_to_update, versions, loaders, loadersList, m_mod_model)); connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({ mod, reason, recover_url }); }); From 00b83efb9a79044d71dc4747e9ffaf1562590759 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 24 Jun 2024 20:12:40 +0300 Subject: [PATCH 14/37] fix build Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 1 - launcher/modplatform/CheckUpdateTask.h | 9 +-------- launcher/modplatform/ModIndex.h | 3 +-- launcher/modplatform/flame/FlameCheckUpdate.cpp | 2 +- launcher/modplatform/flame/FlameCheckUpdate.h | 3 +-- launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp | 9 ++++----- launcher/modplatform/modrinth/ModrinthCheckUpdate.h | 1 - launcher/screenshots/ImgurAlbumCreation.cpp | 4 ++-- launcher/screenshots/ImgurUpload.cpp | 4 ++-- launcher/ui/dialogs/ModUpdateDialog.cpp | 10 ++-------- 10 files changed, 14 insertions(+), 32 deletions(-) diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index cc92328eae..b9288d2b34 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -29,7 +29,6 @@ #include "modplatform/ResourceAPI.h" #include "modplatform/flame/FlameAPI.h" #include "modplatform/modrinth/ModrinthAPI.h" -#include "tasks/ConcurrentTask.h" #include "tasks/SequentialTask.h" #include "ui/pages/modplatform/ModModel.h" #include "ui/pages/modplatform/flame/FlameResourceModels.h" diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index fecb842fd3..d411409d16 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -14,15 +14,9 @@ class CheckUpdateTask : public Task { public: CheckUpdateTask(QList& mods, std::list& mcVersions, - std::optional loaders, QList loadersList, std::shared_ptr mods_folder) - : Task(nullptr) - , m_mods(mods) - , m_game_versions(mcVersions) - , m_loaders(loaders) - , m_loaders_list(loadersList) - , m_mods_folder(mods_folder){}; + : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders_list(loadersList), m_mods_folder(mods_folder){}; struct UpdatableMod { QString name; @@ -72,7 +66,6 @@ class CheckUpdateTask : public Task { protected: QList& m_mods; std::list& m_game_versions; - std::optional m_loaders; QList m_loaders_list; std::shared_ptr m_mods_folder; diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 91c9898a95..e3fe69e0cf 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -25,7 +25,6 @@ #include #include #include -#include class QIODevice; @@ -44,7 +43,7 @@ namespace ProviderCapabilities { const char* name(ResourceProvider); QString readableName(ResourceProvider); QStringList hashType(ResourceProvider); -}; // namespace ProviderCapabilities +} // namespace ProviderCapabilities struct ModpackAuthor { QString name; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index 9deffce545..957bc19bc4 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -132,7 +132,7 @@ void FlameCheckUpdate::executeTask() setStatus(tr("Getting API response from CurseForge for '%1'...").arg(mod->name())); setProgress(i++, m_mods.size()); - auto latest_vers = api.getLatestVersions({ { mod->metadata()->project_id.toString() }, m_game_versions, m_loaders }); + auto latest_vers = api.getLatestVersions({ { mod->metadata()->project_id.toString() }, m_game_versions }); // Check if we were aborted while getting the latest version if (m_was_aborted) { diff --git a/launcher/modplatform/flame/FlameCheckUpdate.h b/launcher/modplatform/flame/FlameCheckUpdate.h index bd6806c607..e30ae35b95 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.h +++ b/launcher/modplatform/flame/FlameCheckUpdate.h @@ -9,10 +9,9 @@ class FlameCheckUpdate : public CheckUpdateTask { public: FlameCheckUpdate(QList& mods, std::list& mcVersions, - std::optional loaders, QList loadersList, std::shared_ptr mods_folder) - : CheckUpdateTask(mods, mcVersions, loaders, loadersList, mods_folder) + : CheckUpdateTask(mods, mcVersions, loadersList, mods_folder) {} public slots: diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 50fb11f059..0e9e349d96 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -16,10 +16,9 @@ static ModrinthAPI api; ModrinthCheckUpdate::ModrinthCheckUpdate(QList& mods, std::list& mcVersions, - std::optional loaders, QList loadersList, std::shared_ptr mods_folder) - : CheckUpdateTask(mods, mcVersions, loaders, loadersList, mods_folder) + : CheckUpdateTask(mods, mcVersions, loadersList, mods_folder) , m_hash_type(ModPlatform::ProviderCapabilities::hashType(ModPlatform::ResourceProvider::MODRINTH).first()) {} @@ -88,7 +87,7 @@ void ModrinthCheckUpdate::checkVersionsResponse(std::shared_ptr resp try { for (auto hash : m_mappings.keys()) { - if (forceModLoaderCheck && !m_mappings[hash]->loaders().testAnyFlags(loader)) { + if (forceModLoaderCheck && !(m_mappings[hash]->loaders() & loader)) { continue; } auto project_obj = doc[hash].toObject(); @@ -171,7 +170,7 @@ void ModrinthCheckUpdate::getUpdateModsForLoader(ModPlatform::ModLoaderTypes loa QStringList hashes; if (forceModLoaderCheck) { for (auto hash : m_mappings.keys()) { - if (m_mappings[hash]->loaders().testAnyFlags(loader)) { + if (m_mappings[hash]->loaders() & loader) { hashes.append(hash); } } @@ -211,7 +210,7 @@ void ModrinthCheckUpdate::checkNextLoader() m_next_loader_idx++; setProgress(m_next_loader_idx * 2 - 1, 9); for (auto m : m_mappings) { - if (m->loaders().testAnyFlag(flag)) { + if (m->loaders() & flag) { getUpdateModsForLoader(flag, true); return; } diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h index 2abd51970c..dab4bda2f5 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h @@ -8,7 +8,6 @@ class ModrinthCheckUpdate : public CheckUpdateTask { public: ModrinthCheckUpdate(QList& mods, std::list& mcVersions, - std::optional loaders, QList loadersList, std::shared_ptr mods_folder); diff --git a/launcher/screenshots/ImgurAlbumCreation.cpp b/launcher/screenshots/ImgurAlbumCreation.cpp index c63c8b39b4..d19f251eae 100644 --- a/launcher/screenshots/ImgurAlbumCreation.cpp +++ b/launcher/screenshots/ImgurAlbumCreation.cpp @@ -65,7 +65,7 @@ QNetworkReply* ImgurAlbumCreation::getReply(QNetworkRequest& request) } const QByteArray data = "deletehashes=" + hashes.join(',').toUtf8() + "&title=Minecraft%20Screenshots&privacy=hidden"; return m_network->post(request, data); -}; +} void ImgurAlbumCreation::init() { @@ -81,7 +81,7 @@ auto ImgurAlbumCreation::Sink::init(QNetworkRequest& request) -> Task::State { m_output.clear(); return Task::State::Running; -}; +} auto ImgurAlbumCreation::Sink::write(QByteArray& data) -> Task::State { diff --git a/launcher/screenshots/ImgurUpload.cpp b/launcher/screenshots/ImgurUpload.cpp index 941b92ce67..8f60148bf7 100644 --- a/launcher/screenshots/ImgurUpload.cpp +++ b/launcher/screenshots/ImgurUpload.cpp @@ -81,13 +81,13 @@ QNetworkReply* ImgurUpload::getReply(QNetworkRequest& request) multipart->append(namePart); return m_network->post(request, multipart); -}; +} auto ImgurUpload::Sink::init(QNetworkRequest& request) -> Task::State { m_output.clear(); return Task::State::Running; -}; +} auto ImgurUpload::Sink::write(QByteArray& data) -> Task::State { diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 5cb25b218a..ed984ccbcd 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -31,11 +31,6 @@ static std::list mcVersions(BaseInstance* inst) return { static_cast(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion() }; } -static std::optional mcLoaders(BaseInstance* inst) -{ - return static_cast(inst)->getPackProfile()->getSupportedModLoaders(); -} - static QList mcLoadersList(BaseInstance* inst) { return static_cast(inst)->getPackProfile()->getModLoadersList(); @@ -92,13 +87,12 @@ void ModUpdateDialog::checkCandidates() } auto versions = mcVersions(m_instance); - auto loaders = mcLoaders(m_instance); auto loadersList = mcLoadersList(m_instance); SequentialTask check_task(m_parent, tr("Checking for updates")); if (!m_modrinth_to_update.empty()) { - m_modrinth_check_task.reset(new ModrinthCheckUpdate(m_modrinth_to_update, versions, loaders, loadersList, m_mod_model)); + m_modrinth_check_task.reset(new ModrinthCheckUpdate(m_modrinth_to_update, versions, loadersList, m_mod_model)); connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({ mod, reason, recover_url }); }); @@ -106,7 +100,7 @@ void ModUpdateDialog::checkCandidates() } if (!m_flame_to_update.empty()) { - m_flame_check_task.reset(new FlameCheckUpdate(m_flame_to_update, versions, loaders, loadersList, m_mod_model)); + m_flame_check_task.reset(new FlameCheckUpdate(m_flame_to_update, versions, loadersList, m_mod_model)); connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({ mod, reason, recover_url }); }); From 14b09549e1fc429b87a5c8345ceda069244b6484 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 25 Jun 2024 01:50:37 -0700 Subject: [PATCH 15/37] feat(instanceList) persist "ungrouped" hidden state Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/InstanceList.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index 0d53c7f253..3f835cfaf7 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -710,6 +710,12 @@ void InstanceList::saveGroupList() groupsArr.insert(name, groupObj); } toplevel.insert("groups", groupsArr); + // empty string represents ungrouped "group" + if (m_collapsedGroups.contains("")) { + QJsonObject ungrouped; + ungrouped.insert("hidden", QJsonValue(true)); + toplevel.insert("ungrouped", ungrouped); + } QJsonDocument doc(toplevel); try { FS::write(groupFileName, doc.toJson()); @@ -805,6 +811,16 @@ void InstanceList::loadGroupList() increaseGroupCount(groupName); } } + + bool ungroupedHidden = false; + if (rootObj.value("ungrouped").isObject()) { + QJsonObject ungrouped = rootObj.value("ungrouped").toObject(); + ungroupedHidden = ungrouped.value("hidden").toBool(false); + } + if (ungroupedHidden) { + // empty string represents ungrouped "group" + m_collapsedGroups.insert(""); + } m_groupsLoaded = true; qDebug() << "Group list loaded."; } From 046e3588afc57df5669e1b9c230275b7a5b44bc0 Mon Sep 17 00:00:00 2001 From: Tayou Date: Sun, 30 Jun 2024 21:35:03 +0200 Subject: [PATCH 16/37] more system themes initial changes Signed-off-by: Tayou --- launcher/Application.cpp | 4 ++-- launcher/ui/themes/SystemTheme.cpp | 34 +++++++++++++++++++++-------- launcher/ui/themes/SystemTheme.h | 6 +++-- launcher/ui/themes/ThemeManager.cpp | 30 +++++++++++++++++++++---- launcher/ui/themes/ThemeManager.h | 1 + 5 files changed, 58 insertions(+), 17 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 7ae66e13ae..327b63b029 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1073,8 +1073,8 @@ bool Application::createSetupWizard() // set default theme after going into theme wizard if (!validIcons) settings()->set("IconTheme", QString("pe_colored")); - if (!validWidgets) - settings()->set("ApplicationTheme", QString("system")); + //if (!validWidgets) + //settings()->set("ApplicationTheme", QString("system")); m_themeManager->applyCurrentlySelectedTheme(true); diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index cefe664db9..d927d2207e 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -43,25 +43,33 @@ SystemTheme::SystemTheme() { + themeName = QObject::tr("System"); themeDebugLog() << "Determining System Theme..."; const auto& style = QApplication::style(); - systemPalette = QApplication::palette(); - QString lowerThemeName = style->objectName(); + colorPalette = QApplication::palette(); + QString lowerThemeName = style->name(); themeDebugLog() << "System theme seems to be:" << lowerThemeName; QStringList styles = QStyleFactory::keys(); for (auto& st : styles) { themeDebugLog() << "Considering theme from theme factory:" << st.toLower(); if (st.toLower() == lowerThemeName) { - systemTheme = st; - themeDebugLog() << "System theme has been determined to be:" << systemTheme; + widgetTheme = st; + themeDebugLog() << "System theme has been determined to be:" << widgetTheme; return; } } // fall back to fusion if we can't find the current theme. - systemTheme = "Fusion"; + widgetTheme = "Fusion"; themeDebugLog() << "System theme not found, defaulted to Fusion"; } +SystemTheme::SystemTheme(QString& styleName) +{ + themeName = styleName; + widgetTheme = styleName; + colorPalette = QApplication::palette(); +} + void SystemTheme::apply(bool initial) { // See https://github.com/MultiMC/Launcher/issues/1790 @@ -76,22 +84,30 @@ void SystemTheme::apply(bool initial) QString SystemTheme::id() { - return "system"; + return themeName; } QString SystemTheme::name() { - return QObject::tr("System"); + if (themeName.toLower() == "windowsvista") { + return QObject::tr("Windows Vista"); + } else if (themeName.toLower() == "windows") { + return QObject::tr("Windows 9x"); + } else if (themeName.toLower() == "windows11") { + return QObject::tr("Windows 11"); + } else { + return themeName; + } } QString SystemTheme::qtTheme() { - return systemTheme; + return widgetTheme; } QPalette SystemTheme::colorScheme() { - return systemPalette; + return colorPalette; } QString SystemTheme::appStyleSheet() diff --git a/launcher/ui/themes/SystemTheme.h b/launcher/ui/themes/SystemTheme.h index 4f7d83e57e..a0e77fae16 100644 --- a/launcher/ui/themes/SystemTheme.h +++ b/launcher/ui/themes/SystemTheme.h @@ -39,6 +39,7 @@ class SystemTheme : public ITheme { public: SystemTheme(); + explicit SystemTheme(QString& themeName); virtual ~SystemTheme() {} void apply(bool initial) override; @@ -53,6 +54,7 @@ class SystemTheme : public ITheme { QColor fadeColor() override; private: - QPalette systemPalette; - QString systemTheme; + QPalette colorPalette; + QString widgetTheme; + QString themeName; }; diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 1cb83ca26c..601bc66c2a 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "Exception.h" #include "ui/themes/BrightTheme.h" #include "ui/themes/CatPack.h" @@ -119,14 +121,30 @@ void ThemeManager::initializeIcons() void ThemeManager::initializeWidgets() { + themeDebugLog() << "Determining System Widget Theme..."; + const auto& style = QApplication::style(); + currentlySelectedSystemTheme = style->name(); + themeDebugLog() << "System theme seems to be:" << currentlySelectedSystemTheme; + themeDebugLog() << "<> Initializing Widget Themes"; - themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); + //themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); auto darkThemeId = addTheme(std::make_unique()); themeDebugLog() << "Loading Built-in Theme:" << darkThemeId; themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); - // TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in - // dropdown?) + themeDebugLog() << "<> Initializing System Themes"; + QStringList styles = QStyleFactory::keys(); + for (auto& st : styles) { +#if Q_OS_WINDOWS + if (QSysInfo::productVersion() != "11" && st == "windows11") { + continue; + } +#endif + themeDebugLog() << "Loading System Theme:" << addTheme(std::make_unique(st)); + } + + // TODO: need some way to differentiate same name themes in different subdirectories + // (maybe smaller grey text next to theme name in dropdown?) if (!m_applicationThemeFolder.mkpath(".")) themeWarningLog() << "Couldn't create theme folder"; @@ -238,7 +256,11 @@ void ThemeManager::applyCurrentlySelectedTheme(bool initial) auto settings = APPLICATION->settings(); setIconTheme(settings->get("IconTheme").toString()); themeDebugLog() << "<> Icon theme set."; - setApplicationTheme(settings->get("ApplicationTheme").toString(), initial); + auto applicationTheme = settings->get("ApplicationTheme").toString(); + if (applicationTheme == "") { + applicationTheme = currentlySelectedSystemTheme; + } + setApplicationTheme(applicationTheme, initial); themeDebugLog() << "<> Application theme set."; } diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 47b9589e3f..ddf619a800 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -64,6 +64,7 @@ class ThemeManager { QDir m_applicationThemeFolder{ "themes" }; QDir m_catPacksFolder{ "catpacks" }; std::map> m_cat_packs; + QString currentlySelectedSystemTheme; void initializeThemes(); void initializeCatPacks(); From f0c9b520557e467b99a2547360260c494f9f218d Mon Sep 17 00:00:00 2001 From: Tayou Date: Sun, 30 Jun 2024 21:41:37 +0200 Subject: [PATCH 17/37] oop Signed-off-by: Tayou --- launcher/ui/themes/SystemTheme.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index d927d2207e..aa5af95bf6 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -47,7 +47,7 @@ SystemTheme::SystemTheme() themeDebugLog() << "Determining System Theme..."; const auto& style = QApplication::style(); colorPalette = QApplication::palette(); - QString lowerThemeName = style->name(); + QString lowerThemeName = style->objectName(); themeDebugLog() << "System theme seems to be:" << lowerThemeName; QStringList styles = QStyleFactory::keys(); for (auto& st : styles) { From a184b26a00be14c84bc86663de2fedd2c9ca8610 Mon Sep 17 00:00:00 2001 From: Tayou Date: Sun, 30 Jun 2024 21:47:52 +0200 Subject: [PATCH 18/37] #ifdef, not #if... I'm smort Signed-off-by: Tayou --- launcher/ui/themes/ThemeManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 601bc66c2a..e4ad49db3f 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -135,7 +135,7 @@ void ThemeManager::initializeWidgets() themeDebugLog() << "<> Initializing System Themes"; QStringList styles = QStyleFactory::keys(); for (auto& st : styles) { -#if Q_OS_WINDOWS +#ifdef Q_OS_WINDOWS if (QSysInfo::productVersion() != "11" && st == "windows11") { continue; } From 7104f8909dace5139dcc75b8f6be75cd9ef063a1 Mon Sep 17 00:00:00 2001 From: Tayou Date: Sun, 30 Jun 2024 21:52:26 +0200 Subject: [PATCH 19/37] another oop Signed-off-by: Tayou --- launcher/ui/themes/ThemeManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index e4ad49db3f..00b89b780b 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -123,7 +123,7 @@ void ThemeManager::initializeWidgets() { themeDebugLog() << "Determining System Widget Theme..."; const auto& style = QApplication::style(); - currentlySelectedSystemTheme = style->name(); + currentlySelectedSystemTheme = style->objectName(); themeDebugLog() << "System theme seems to be:" << currentlySelectedSystemTheme; themeDebugLog() << "<> Initializing Widget Themes"; From 4f795eb6efd967e3d38fd6f7417bc8313dd6659a Mon Sep 17 00:00:00 2001 From: Tayou Date: Sun, 30 Jun 2024 22:06:01 +0200 Subject: [PATCH 20/37] format Signed-off-by: Tayou --- launcher/Application.cpp | 4 ++-- launcher/ui/themes/ThemeManager.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 327b63b029..6254e38fef 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1073,8 +1073,8 @@ bool Application::createSetupWizard() // set default theme after going into theme wizard if (!validIcons) settings()->set("IconTheme", QString("pe_colored")); - //if (!validWidgets) - //settings()->set("ApplicationTheme", QString("system")); + // if (!validWidgets) + // settings()->set("ApplicationTheme", QString("system")); m_themeManager->applyCurrentlySelectedTheme(true); diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 00b89b780b..b3461f6542 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -23,8 +23,8 @@ #include #include #include -#include #include +#include #include "Exception.h" #include "ui/themes/BrightTheme.h" #include "ui/themes/CatPack.h" @@ -127,7 +127,7 @@ void ThemeManager::initializeWidgets() themeDebugLog() << "System theme seems to be:" << currentlySelectedSystemTheme; themeDebugLog() << "<> Initializing Widget Themes"; - //themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); + // themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); auto darkThemeId = addTheme(std::make_unique()); themeDebugLog() << "Loading Built-in Theme:" << darkThemeId; themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); From d70be5121c3f67c1fa171116fd183be5b814f60b Mon Sep 17 00:00:00 2001 From: Tayou Date: Sun, 30 Jun 2024 23:27:45 +0200 Subject: [PATCH 21/37] tooltips Signed-off-by: Tayou --- launcher/ui/themes/BrightTheme.cpp | 38 +++++++++++++++++++ launcher/ui/themes/BrightTheme.h | 35 +++++++++++++++++ launcher/ui/themes/CustomTheme.cpp | 6 ++- launcher/ui/themes/CustomTheme.h | 9 ++++- launcher/ui/themes/DarkTheme.cpp | 38 +++++++++++++++++++ launcher/ui/themes/DarkTheme.h | 35 +++++++++++++++++ launcher/ui/themes/ITheme.h | 1 + launcher/ui/themes/SystemTheme.cpp | 20 +++++++++- launcher/ui/themes/SystemTheme.h | 3 +- launcher/ui/themes/ThemeManager.cpp | 6 +-- launcher/ui/themes/ThemeManager.h | 2 +- .../ui/widgets/ThemeCustomizationWidget.cpp | 6 ++- 12 files changed, 189 insertions(+), 10 deletions(-) diff --git a/launcher/ui/themes/BrightTheme.cpp b/launcher/ui/themes/BrightTheme.cpp index ffccdaab12..39a5bfd148 100644 --- a/launcher/ui/themes/BrightTheme.cpp +++ b/launcher/ui/themes/BrightTheme.cpp @@ -1,3 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2024 Tayou + * + * 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 + * + * 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 "BrightTheme.h" #include @@ -55,3 +89,7 @@ QString BrightTheme::appStyleSheet() { return QString(); } +QString BrightTheme::tooltip() +{ + return QString(); +} diff --git a/launcher/ui/themes/BrightTheme.h b/launcher/ui/themes/BrightTheme.h index 44a7674924..750e7bfc51 100644 --- a/launcher/ui/themes/BrightTheme.h +++ b/launcher/ui/themes/BrightTheme.h @@ -1,3 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2024 Tayou + * + * 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 + * + * 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 "FusionTheme.h" @@ -8,6 +42,7 @@ class BrightTheme : public FusionTheme { QString id() override; QString name() override; + QString tooltip() override; bool hasStyleSheet() override; QString appStyleSheet() override; bool hasColorScheme() override; diff --git a/launcher/ui/themes/CustomTheme.cpp b/launcher/ui/themes/CustomTheme.cpp index 4859983c6e..22b366b624 100644 --- a/launcher/ui/themes/CustomTheme.cpp +++ b/launcher/ui/themes/CustomTheme.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2024 Tayou * * 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 @@ -285,3 +285,7 @@ QString CustomTheme::qtTheme() { return m_widgets; } +QString CustomTheme::tooltip() +{ + return m_tooltip; +} diff --git a/launcher/ui/themes/CustomTheme.h b/launcher/ui/themes/CustomTheme.h index 3ec4cafa21..761a2bd90f 100644 --- a/launcher/ui/themes/CustomTheme.h +++ b/launcher/ui/themes/CustomTheme.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2024 Tayou * * 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 @@ -44,6 +44,7 @@ class CustomTheme : public ITheme { QString id() override; QString name() override; + QString tooltip() override; bool hasStyleSheet() override; QString appStyleSheet() override; bool hasColorScheme() override; @@ -62,4 +63,10 @@ class CustomTheme : public ITheme { QString m_id; QString m_widgets; QString m_qssFilePath; + /** + * The tooltip could be defined in the theme json, + * or composed of other fields that could be in there. + * like author, license, etc. + */ + QString m_tooltip = ""; }; diff --git a/launcher/ui/themes/DarkTheme.cpp b/launcher/ui/themes/DarkTheme.cpp index c3a68a2d43..429d046ac8 100644 --- a/launcher/ui/themes/DarkTheme.cpp +++ b/launcher/ui/themes/DarkTheme.cpp @@ -1,3 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2024 Tayou + * + * 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 + * + * 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 "DarkTheme.h" #include @@ -56,3 +90,7 @@ QString DarkTheme::appStyleSheet() { return "QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }"; } +QString DarkTheme::tooltip() +{ + return ""; +} diff --git a/launcher/ui/themes/DarkTheme.h b/launcher/ui/themes/DarkTheme.h index 431e9a735c..819f6a9343 100644 --- a/launcher/ui/themes/DarkTheme.h +++ b/launcher/ui/themes/DarkTheme.h @@ -1,3 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2024 Tayou + * + * 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 + * + * 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 "FusionTheme.h" @@ -8,6 +42,7 @@ class DarkTheme : public FusionTheme { QString id() override; QString name() override; + QString tooltip() override; bool hasStyleSheet() override; QString appStyleSheet() override; bool hasColorScheme() override; diff --git a/launcher/ui/themes/ITheme.h b/launcher/ui/themes/ITheme.h index d85e7f9833..45d3e27390 100644 --- a/launcher/ui/themes/ITheme.h +++ b/launcher/ui/themes/ITheme.h @@ -44,6 +44,7 @@ class ITheme { virtual void apply(bool initial); virtual QString id() = 0; virtual QString name() = 0; + virtual QString tooltip() = 0; virtual bool hasStyleSheet() = 0; virtual QString appStyleSheet() = 0; virtual QString qtTheme() = 0; diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index aa5af95bf6..a46b2002ac 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2024 Tayou * Copyright (C) 2024 TheKodeToad * * This program is free software: you can redistribute it and/or modify @@ -35,7 +35,6 @@ */ #include "SystemTheme.h" #include -#include #include #include #include "HintOverrideProxyStyle.h" @@ -100,6 +99,23 @@ QString SystemTheme::name() } } +QString SystemTheme::tooltip() +{ + if (themeName.toLower() == "windowsvista") { + return QObject::tr("Widget style trying to look like your win32 theme"); + } else if (themeName.toLower() == "windows") { + return QObject::tr("Windows 9x inspired widget style"); + } else if (themeName.toLower() == "windows11") { + return QObject::tr("WinUI 3 inspired Qt widget style"); + } else if (themeName.toLower() == "fusion") { + return QObject::tr("The default Qt widget style"); + } else if (themeName.toLower() == "system") { + return QObject::tr("Your current system theme") + " (" + widgetTheme + ")"; + } else { + return ""; + } +} + QString SystemTheme::qtTheme() { return widgetTheme; diff --git a/launcher/ui/themes/SystemTheme.h b/launcher/ui/themes/SystemTheme.h index a0e77fae16..bcfe342889 100644 --- a/launcher/ui/themes/SystemTheme.h +++ b/launcher/ui/themes/SystemTheme.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2024 Tayou * * 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 @@ -45,6 +45,7 @@ class SystemTheme : public ITheme { QString id() override; QString name() override; + QString tooltip() override; QString qtTheme() override; bool hasStyleSheet() override; QString appStyleSheet() override; diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index b3461f6542..ac2bf26dc1 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2024 Tayou * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify @@ -127,12 +127,12 @@ void ThemeManager::initializeWidgets() themeDebugLog() << "System theme seems to be:" << currentlySelectedSystemTheme; themeDebugLog() << "<> Initializing Widget Themes"; - // themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); + themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); auto darkThemeId = addTheme(std::make_unique()); themeDebugLog() << "Loading Built-in Theme:" << darkThemeId; themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); - themeDebugLog() << "<> Initializing System Themes"; + themeDebugLog() << "<> Initializing System Widget Themes"; QStringList styles = QStyleFactory::keys(); for (auto& st : styles) { #ifdef Q_OS_WINDOWS diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index ddf619a800..9d01d38e73 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2024 Tayou * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp index 9c5df0067b..7a54bd3900 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp +++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Tayou + * Copyright (C) 2024 Tayou * * 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 @@ -151,6 +151,10 @@ void ThemeCustomizationWidget::loadSettings() int idx = 0; for (auto& theme : themes) { ui->widgetStyleComboBox->addItem(theme->name(), theme->id()); + if (theme->tooltip() != "") { + int index = ui->widgetStyleComboBox->count() - 1; + ui->widgetStyleComboBox->setItemData(index, theme->tooltip(), Qt::ToolTipRole); + } if (currentTheme == theme->id()) { ui->widgetStyleComboBox->setCurrentIndex(idx); } From dbcfefca1b0e537aaec2bfe0ddc091c5f994317d Mon Sep 17 00:00:00 2001 From: Tayou Date: Mon, 1 Jul 2024 23:05:54 +0200 Subject: [PATCH 22/37] fix system theme Signed-off-by: Tayou --- launcher/Application.cpp | 4 ++-- launcher/ui/themes/SystemTheme.cpp | 30 +++++------------------------ launcher/ui/themes/SystemTheme.h | 3 +-- launcher/ui/themes/ThemeManager.cpp | 2 +- 4 files changed, 9 insertions(+), 30 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 6254e38fef..7ae66e13ae 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1073,8 +1073,8 @@ bool Application::createSetupWizard() // set default theme after going into theme wizard if (!validIcons) settings()->set("IconTheme", QString("pe_colored")); - // if (!validWidgets) - // settings()->set("ApplicationTheme", QString("system")); + if (!validWidgets) + settings()->set("ApplicationTheme", QString("system")); m_themeManager->applyCurrentlySelectedTheme(true); diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index a46b2002ac..70de218942 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -40,31 +40,9 @@ #include "HintOverrideProxyStyle.h" #include "ThemeManager.h" -SystemTheme::SystemTheme() +SystemTheme::SystemTheme(QString& styleName, bool isSystemTheme) { - themeName = QObject::tr("System"); - themeDebugLog() << "Determining System Theme..."; - const auto& style = QApplication::style(); - colorPalette = QApplication::palette(); - QString lowerThemeName = style->objectName(); - themeDebugLog() << "System theme seems to be:" << lowerThemeName; - QStringList styles = QStyleFactory::keys(); - for (auto& st : styles) { - themeDebugLog() << "Considering theme from theme factory:" << st.toLower(); - if (st.toLower() == lowerThemeName) { - widgetTheme = st; - themeDebugLog() << "System theme has been determined to be:" << widgetTheme; - return; - } - } - // fall back to fusion if we can't find the current theme. - widgetTheme = "Fusion"; - themeDebugLog() << "System theme not found, defaulted to Fusion"; -} - -SystemTheme::SystemTheme(QString& styleName) -{ - themeName = styleName; + themeName = isSystemTheme ? "system" : styleName; widgetTheme = styleName; colorPalette = QApplication::palette(); } @@ -94,6 +72,8 @@ QString SystemTheme::name() return QObject::tr("Windows 9x"); } else if (themeName.toLower() == "windows11") { return QObject::tr("Windows 11"); + } else if (themeName.toLower() == "system") { + return QObject::tr("System"); } else { return themeName; } @@ -110,7 +90,7 @@ QString SystemTheme::tooltip() } else if (themeName.toLower() == "fusion") { return QObject::tr("The default Qt widget style"); } else if (themeName.toLower() == "system") { - return QObject::tr("Your current system theme") + " (" + widgetTheme + ")"; + return QObject::tr("Your current system theme"); } else { return ""; } diff --git a/launcher/ui/themes/SystemTheme.h b/launcher/ui/themes/SystemTheme.h index bcfe342889..5c58856cb5 100644 --- a/launcher/ui/themes/SystemTheme.h +++ b/launcher/ui/themes/SystemTheme.h @@ -38,8 +38,7 @@ class SystemTheme : public ITheme { public: - SystemTheme(); - explicit SystemTheme(QString& themeName); + SystemTheme(QString& themeName, bool isSystemTheme = false); virtual ~SystemTheme() {} void apply(bool initial) override; diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index ac2bf26dc1..d57e166f40 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -127,7 +127,7 @@ void ThemeManager::initializeWidgets() themeDebugLog() << "System theme seems to be:" << currentlySelectedSystemTheme; themeDebugLog() << "<> Initializing Widget Themes"; - themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); + themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique(currentlySelectedSystemTheme, true)); auto darkThemeId = addTheme(std::make_unique()); themeDebugLog() << "Loading Built-in Theme:" << darkThemeId; themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); From 9b172278f8ca81f7dbf3b698dbfbbc37c40f8a81 Mon Sep 17 00:00:00 2001 From: Kationor Date: Wed, 3 Jul 2024 12:39:28 +0200 Subject: [PATCH 23/37] Add ModpackUpdatePromptDisabled setting When creating an instance of a modpack that's already associated with another instance, the user gets asked if they want to update that instance instead. This commit introduces a setting to suppress the prompt and directly create the new instance. Signed-off-by: Kationor --- launcher/Application.cpp | 1 + launcher/InstanceTask.cpp | 5 +++++ launcher/ui/pages/global/LauncherPage.cpp | 2 ++ launcher/ui/pages/global/LauncherPage.ui | 10 ++++++++++ 4 files changed, 18 insertions(+) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 7ae66e13ae..b88b720060 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -662,6 +662,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // Minecraft mods m_settings->registerSetting("ModMetadataDisabled", false); m_settings->registerSetting("ModDependenciesDisabled", false); + m_settings->registerSetting("ModpackUpdatePromptDisabled", false); // Minecraft offline player name m_settings->registerSetting("LastOfflinePlayerName", ""); diff --git a/launcher/InstanceTask.cpp b/launcher/InstanceTask.cpp index 53476897cf..ffa8751197 100644 --- a/launcher/InstanceTask.cpp +++ b/launcher/InstanceTask.cpp @@ -1,5 +1,7 @@ #include "InstanceTask.h" +#include "Application.h" +#include "settings/SettingsObject.h" #include "ui/dialogs/CustomMessageBox.h" #include @@ -22,6 +24,9 @@ InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& ol ShouldUpdate askIfShouldUpdate(QWidget* parent, QString original_version_name) { + if (APPLICATION->settings()->get("ModpackUpdatePromptDisabled").toBool()) + return ShouldUpdate::SkipUpdating; + auto info = CustomMessageBox::selectable( parent, QObject::tr("Similar modpack was found!"), QObject::tr( diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 6b32e98496..93ff572c2c 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -241,6 +241,7 @@ void LauncherPage::applySettings() // Mods s->set("ModMetadataDisabled", ui->metadataDisableBtn->isChecked()); s->set("ModDependenciesDisabled", ui->dependenciesDisableBtn->isChecked()); + s->set("ModpackUpdatePromptDisabled", ui->modpackUpdatePromptDisableBtn->isChecked()); } void LauncherPage::loadSettings() { @@ -303,6 +304,7 @@ void LauncherPage::loadSettings() ui->metadataDisableBtn->setChecked(s->get("ModMetadataDisabled").toBool()); ui->metadataWarningLabel->setHidden(!ui->metadataDisableBtn->isChecked()); ui->dependenciesDisableBtn->setChecked(s->get("ModDependenciesDisabled").toBool()); + ui->modpackUpdatePromptDisableBtn->setChecked(s->get("ModpackUpdatePromptDisabled").toBool()); } void LauncherPage::refreshFontPreview() diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 1f49a831f9..162b5da453 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -243,6 +243,16 @@ + + + + When creating a new modpack instance, do not suggest updating existing instances. + + + Always create new modpack instance + + + From 83a5fe198413e70d20fa3d08df808b5b3f932bb2 Mon Sep 17 00:00:00 2001 From: Kationor Date: Wed, 3 Jul 2024 23:09:59 +0200 Subject: [PATCH 24/37] Rename setting to SkipModpackUpdatePrompt Was ModpackUpdatePromptDisabled Signed-off-by: Kationor --- launcher/Application.cpp | 2 +- launcher/InstanceTask.cpp | 2 +- launcher/ui/pages/global/LauncherPage.cpp | 4 ++-- launcher/ui/pages/global/LauncherPage.ui | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index b88b720060..06fc685752 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -662,7 +662,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // Minecraft mods m_settings->registerSetting("ModMetadataDisabled", false); m_settings->registerSetting("ModDependenciesDisabled", false); - m_settings->registerSetting("ModpackUpdatePromptDisabled", false); + m_settings->registerSetting("SkipModpackUpdatePrompt", false); // Minecraft offline player name m_settings->registerSetting("LastOfflinePlayerName", ""); diff --git a/launcher/InstanceTask.cpp b/launcher/InstanceTask.cpp index ffa8751197..be10bbe07c 100644 --- a/launcher/InstanceTask.cpp +++ b/launcher/InstanceTask.cpp @@ -24,7 +24,7 @@ InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& ol ShouldUpdate askIfShouldUpdate(QWidget* parent, QString original_version_name) { - if (APPLICATION->settings()->get("ModpackUpdatePromptDisabled").toBool()) + if (APPLICATION->settings()->get("SkipModpackUpdatePrompt").toBool()) return ShouldUpdate::SkipUpdating; auto info = CustomMessageBox::selectable( diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 93ff572c2c..179f06bbfb 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -241,7 +241,7 @@ void LauncherPage::applySettings() // Mods s->set("ModMetadataDisabled", ui->metadataDisableBtn->isChecked()); s->set("ModDependenciesDisabled", ui->dependenciesDisableBtn->isChecked()); - s->set("ModpackUpdatePromptDisabled", ui->modpackUpdatePromptDisableBtn->isChecked()); + s->set("SkipModpackUpdatePrompt", ui->skipModpackUpdatePromptBtn->isChecked()); } void LauncherPage::loadSettings() { @@ -304,7 +304,7 @@ void LauncherPage::loadSettings() ui->metadataDisableBtn->setChecked(s->get("ModMetadataDisabled").toBool()); ui->metadataWarningLabel->setHidden(!ui->metadataDisableBtn->isChecked()); ui->dependenciesDisableBtn->setChecked(s->get("ModDependenciesDisabled").toBool()); - ui->modpackUpdatePromptDisableBtn->setChecked(s->get("ModpackUpdatePromptDisabled").toBool()); + ui->skipModpackUpdatePromptBtn->setChecked(s->get("SkipModpackUpdatePrompt").toBool()); } void LauncherPage::refreshFontPreview() diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 162b5da453..b3d677ce28 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -244,12 +244,12 @@ - + - When creating a new modpack instance, do not suggest updating existing instances. + When creating a new modpack instance, do not suggest updating existing instances instead. - Always create new modpack instance + Skip modpack update prompt From 1dd21a5e4a5360ceac5f549fb613722487bfb4f1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 4 Jul 2024 16:38:40 +0300 Subject: [PATCH 25/37] fix crash with hash task Signed-off-by: Trial97 --- launcher/modplatform/helpers/HashUtils.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp index f20af1f091..51789910c5 100644 --- a/launcher/modplatform/helpers/HashUtils.cpp +++ b/launcher/modplatform/helpers/HashUtils.cpp @@ -18,8 +18,7 @@ Hasher::Ptr createHasher(QString file_path, ModPlatform::ResourceProvider provid case ModPlatform::ResourceProvider::FLAME: return makeShared(file_path, Algorithm::Murmur2); default: - qCritical() << "[Hashing]" - << "Unrecognized mod platform!"; + qCritical() << "[Hashing]" << "Unrecognized mod platform!"; return nullptr; } } @@ -129,6 +128,10 @@ QString hash(QString fileName, Algorithm type) QFile file(fileName); return hash(&file, type); } +QString hashFile(QString fileName, Algorithm type) +{ + return hash(fileName, type); +} QString hash(QByteArray data, Algorithm type) { @@ -138,7 +141,7 @@ QString hash(QByteArray data, Algorithm type) void Hasher::executeTask() { - m_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return hash(m_path, m_alg); }); + m_future = QtConcurrent::run(QThreadPool::globalInstance(), hashFile, m_path, m_alg); connect(&m_watcher, &QFutureWatcher::finished, this, [this] { if (m_future.isCanceled()) { emitAborted(); From 5d8d1c4b90960e3469bb04e566c79afb513da529 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 4 Jul 2024 16:47:27 +0300 Subject: [PATCH 26/37] transform hashFile to lambda Signed-off-by: Trial97 --- launcher/modplatform/helpers/HashUtils.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp index 51789910c5..a3b8d904cb 100644 --- a/launcher/modplatform/helpers/HashUtils.cpp +++ b/launcher/modplatform/helpers/HashUtils.cpp @@ -128,10 +128,6 @@ QString hash(QString fileName, Algorithm type) QFile file(fileName); return hash(&file, type); } -QString hashFile(QString fileName, Algorithm type) -{ - return hash(fileName, type); -} QString hash(QByteArray data, Algorithm type) { @@ -141,7 +137,8 @@ QString hash(QByteArray data, Algorithm type) void Hasher::executeTask() { - m_future = QtConcurrent::run(QThreadPool::globalInstance(), hashFile, m_path, m_alg); + m_future = QtConcurrent::run( + QThreadPool::globalInstance(), [](QString fileName, Algorithm type) { return hash(fileName, type); }, m_path, m_alg); connect(&m_watcher, &QFutureWatcher::finished, this, [this] { if (m_future.isCanceled()) { emitAborted(); From a6ae078e7e8cd9a9ab46ab3f18e824516766a5e4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 6 Jul 2024 09:30:26 +0300 Subject: [PATCH 27/37] add docs to Library.cpp Signed-off-by: Trial97 --- launcher/minecraft/Library.cpp | 101 +++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/launcher/minecraft/Library.cpp b/launcher/minecraft/Library.cpp index 4e30f72d19..a20d6c5152 100644 --- a/launcher/minecraft/Library.cpp +++ b/launcher/minecraft/Library.cpp @@ -42,6 +42,20 @@ #include #include +/** + * @brief Collect applicable files for the library. + * + * Depending on whether the library is native or not, it adds paths to the + * appropriate lists for jar files, native libraries for 32-bit, and native + * libraries for 64-bit. + * + * @param runtimeContext The current runtime context. + * @param jar List to store paths for jar files. + * @param native List to store paths for native libraries. + * @param native32 List to store paths for 32-bit native libraries. + * @param native64 List to store paths for 64-bit native libraries. + * @param overridePath Optional path to override the default storage path. + */ void Library::getApplicableFiles(const RuntimeContext& runtimeContext, QStringList& jar, QStringList& native, @@ -50,6 +64,7 @@ void Library::getApplicableFiles(const RuntimeContext& runtimeContext, const QString& overridePath) const { bool local = isLocal(); + // Lambda function to get the absolute file path auto actualPath = [&](QString relPath) { relPath = FS::RemoveInvalidPathChars(relPath); QFileInfo out(FS::PathCombine(storagePrefix(), relPath)); @@ -59,6 +74,7 @@ void Library::getApplicableFiles(const RuntimeContext& runtimeContext, } return out.absoluteFilePath(); }; + QString raw_storage = storageSuffix(runtimeContext); if (isNative()) { if (raw_storage.contains("${arch}")) { @@ -76,6 +92,19 @@ void Library::getApplicableFiles(const RuntimeContext& runtimeContext, } } +/** + * @brief Get download requests for the library files. + * + * Depending on whether the library is native or not, and the current runtime context, + * this function prepares download requests for the necessary files. It handles both local + * and remote files, checks for stale cache entries, and adds checksummed downloads. + * + * @param runtimeContext The current runtime context. + * @param cache Pointer to the HTTP meta cache. + * @param failedLocalFiles List to store paths for failed local files. + * @param overridePath Optional path to override the default storage path. + * @return QList List of download requests. + */ QList Library::getDownloads(const RuntimeContext& runtimeContext, class HttpMetaCache* cache, QStringList& failedLocalFiles, @@ -85,6 +114,7 @@ QList Library::getDownloads(const RuntimeContext& runtimeC bool stale = isAlwaysStale(); bool local = isLocal(); + // Lambda function to check if a local file exists auto check_local_file = [&](QString storage) { QFileInfo fileinfo(storage); QString fileName = fileinfo.fileName(); @@ -97,6 +127,7 @@ QList Library::getDownloads(const RuntimeContext& runtimeC return true; }; + // Lambda function to add a download request auto add_download = [&](QString storage, QString url, QString sha1) { if (local) { return check_local_file(storage); @@ -197,6 +228,15 @@ QList Library::getDownloads(const RuntimeContext& runtimeC return out; } +/** + * @brief Check if the library is active in the given runtime context. + * + * This function evaluates rules to determine if the library should be active, + * considering both general rules and native compatibility. + * + * @param runtimeContext The current runtime context. + * @return bool True if the library is active, false otherwise. + */ bool Library::isActive(const RuntimeContext& runtimeContext) const { bool result = true; @@ -217,16 +257,35 @@ bool Library::isActive(const RuntimeContext& runtimeContext) const return result; } +/** + * @brief Check if the library is considered local. + * + * @return bool True if the library is local, false otherwise. + */ bool Library::isLocal() const { return m_hint == "local"; } +/** + * @brief Check if the library is always considered stale. + * + * @return bool True if the library is always stale, false otherwise. + */ bool Library::isAlwaysStale() const { return m_hint == "always-stale"; } +/** + * @brief Get the compatible native classifier for the current runtime context. + * + * This function attempts to match the current runtime context with the appropriate + * native classifier. + * + * @param runtimeContext The current runtime context. + * @return QString The compatible native classifier, or an empty string if none is found. + */ QString Library::getCompatibleNative(const RuntimeContext& runtimeContext) const { // try to match precise classifier "[os]-[arch]" @@ -241,16 +300,31 @@ QString Library::getCompatibleNative(const RuntimeContext& runtimeContext) const return entry.value(); } +/** + * @brief Set the storage prefix for the library. + * + * @param prefix The storage prefix to set. + */ void Library::setStoragePrefix(QString prefix) { m_storagePrefix = prefix; } +/** + * @brief Get the default storage prefix for libraries. + * + * @return QString The default storage prefix. + */ QString Library::defaultStoragePrefix() { return "libraries/"; } +/** + * @brief Get the current storage prefix for the library. + * + * @return QString The current storage prefix. + */ QString Library::storagePrefix() const { if (m_storagePrefix.isEmpty()) { @@ -259,6 +333,15 @@ QString Library::storagePrefix() const return m_storagePrefix; } +/** + * @brief Get the filename for the library in the current runtime context. + * + * This function determines the appropriate filename for the library, taking into + * account native classifiers if applicable. + * + * @param runtimeContext The current runtime context. + * @return QString The filename of the library. + */ QString Library::filename(const RuntimeContext& runtimeContext) const { if (!m_filename.isEmpty()) { @@ -280,6 +363,15 @@ QString Library::filename(const RuntimeContext& runtimeContext) const return nativeSpec.getFileName(); } +/** + * @brief Get the display name for the library in the current runtime context. + * + * This function returns the display name for the library, defaulting to the filename + * if no display name is set. + * + * @param runtimeContext The current runtime context. + * @return QString The display name of the library. + */ QString Library::displayName(const RuntimeContext& runtimeContext) const { if (!m_displayname.isEmpty()) @@ -287,6 +379,15 @@ QString Library::displayName(const RuntimeContext& runtimeContext) const return filename(runtimeContext); } +/** + * @brief Get the storage suffix for the library in the current runtime context. + * + * This function determines the appropriate storage suffix for the library, taking into + * account native classifiers if applicable. + * + * @param runtimeContext The current runtime context. + * @return QString The storage suffix of the library. + */ QString Library::storageSuffix(const RuntimeContext& runtimeContext) const { // non-native? use only the gradle specifier From e49e2622fc6ebd3f8061dc13b56a24493ce4019e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 7 Jul 2024 00:21:50 +0000 Subject: [PATCH 28/37] 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 'flake-parts': 'github:hercules-ci/flake-parts/2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8?narHash=sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw%3D' (2024-06-01) → 'github:hercules-ci/flake-parts/9227223f6d922fee3c7b190b2cc238a99527bbb7?narHash=sha256-pQMhCCHyQGRzdfAkdJ4cIWiw%2BJNuWsTX7f0ZYSyz0VY%3D' (2024-07-03) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/3f84a279f1a6290ce154c5531378acc827836fbb?narHash=sha256-u1fA0DYQYdeG%2B5kDm1bOoGcHtX0rtC7qs2YA2N1X%2B%2BI%3D' (2024-06-13) → 'github:NixOS/nixpkgs/9f4128e00b0ae8ec65918efeba59db998750ead6?narHash=sha256-rwz8NJZV%2B387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ%3D' (2024-07-03) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/cc4d466cb1254af050ff7bdf47f6d404a7c646d1?narHash=sha256-7XfBuLULizXjXfBYy/VV%2BSpYMHreNRHk9nKMsm1bgb4%3D' (2024-06-06) → 'github:cachix/pre-commit-hooks.nix/0ff4381bbb8f7a52ca4a851660fc7a437a4c6e07?narHash=sha256-F1h%2BXIsGKT9TkGO3omxDLEb/9jOOsI6NnzsXFsZhry4%3D' (2024-06-24) --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index caed1a708b..961cb20443 100644 --- a/flake.lock +++ b/flake.lock @@ -23,11 +23,11 @@ ] }, "locked": { - "lastModified": 1717285511, - "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "lastModified": 1719994518, + "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", "type": "github" }, "original": { @@ -75,11 +75,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1718276985, - "narHash": "sha256-u1fA0DYQYdeG+5kDm1bOoGcHtX0rtC7qs2YA2N1X++I=", + "lastModified": 1720031269, + "narHash": "sha256-rwz8NJZV+387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3f84a279f1a6290ce154c5531378acc827836fbb", + "rev": "9f4128e00b0ae8ec65918efeba59db998750ead6", "type": "github" }, "original": { @@ -103,11 +103,11 @@ ] }, "locked": { - "lastModified": 1717664902, - "narHash": "sha256-7XfBuLULizXjXfBYy/VV+SpYMHreNRHk9nKMsm1bgb4=", + "lastModified": 1719259945, + "narHash": "sha256-F1h+XIsGKT9TkGO3omxDLEb/9jOOsI6NnzsXFsZhry4=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "cc4d466cb1254af050ff7bdf47f6d404a7c646d1", + "rev": "0ff4381bbb8f7a52ca4a851660fc7a437a4c6e07", "type": "github" }, "original": { From fdcd1068f3e5d859e13eac56964b2eaeb4ac6485 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 8 Jul 2024 14:53:39 +0300 Subject: [PATCH 29/37] remove some poly mentions from the code Signed-off-by: Trial97 --- launcher/InstanceList.cpp | 12 ++++++------ launcher/InstanceList.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index 3f835cfaf7..ab92a6c3c5 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -372,13 +372,13 @@ void InstanceList::undoTrashInstance() auto top = m_trashHistory.pop(); - while (QDir(top.polyPath).exists()) { + while (QDir(top.path).exists()) { top.id += "1"; - top.polyPath += "1"; + top.path += "1"; } - qDebug() << "Moving" << top.trashPath << "back to" << top.polyPath; - QFile(top.trashPath).rename(top.polyPath); + qDebug() << "Moving" << top.trashPath << "back to" << top.path; + QFile(top.trashPath).rename(top.path); m_instanceGroupIndex[top.id] = top.groupName; increaseGroupCount(top.groupName); @@ -635,8 +635,8 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id) QString inst_type = instanceSettings->get("InstanceType").toString(); - // NOTE: Some PolyMC versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a OneSix - // instance + // NOTE: Some PrismMC versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a + // OneSix instance if (inst_type == "OneSix" || inst_type.isEmpty()) { inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot)); } else { diff --git a/launcher/InstanceList.h b/launcher/InstanceList.h index 5ddddee95d..c85fe55c7b 100644 --- a/launcher/InstanceList.h +++ b/launcher/InstanceList.h @@ -58,7 +58,7 @@ enum class GroupsState { NotLoaded, Steady, Dirty }; struct TrashHistoryItem { QString id; - QString polyPath; + QString path; QString trashPath; QString groupName; }; From aeb7f29a5b4a65cccd35d0ff65cfd7101124bb35 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Mon, 8 Jul 2024 15:04:27 +0300 Subject: [PATCH 30/37] Update launcher/InstanceList.cpp Co-authored-by: Tayou Signed-off-by: Alexandru Ionut Tripon --- launcher/InstanceList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index ab92a6c3c5..e1fa755dd3 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -635,7 +635,7 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id) QString inst_type = instanceSettings->get("InstanceType").toString(); - // NOTE: Some PrismMC versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a + // NOTE: Some launcher versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a // OneSix instance if (inst_type == "OneSix" || inst_type.isEmpty()) { inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot)); From 0a543cb66b24d74595073f905d365dbe23c78431 Mon Sep 17 00:00:00 2001 From: izder456 Date: Thu, 11 Jul 2024 20:30:28 -0500 Subject: [PATCH 31/37] FIX launcher/java/JavaUtils.cpp to properly autodetect JVM paths on OpenBSD and FreeBSD Signed-off-by: izder456 --- launcher/java/JavaUtils.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 809d810877..34d893ff2c 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -394,7 +394,7 @@ QList JavaUtils::FindJavaPaths() return javas; } -#elif defined(Q_OS_LINUX) +#elif defined(Q_OS_LINUX) || defined(Q_OS_OPENBSD) || defined(Q_OS_FREEBSD) QList JavaUtils::FindJavaPaths() { QList javas; @@ -419,6 +419,7 @@ QList JavaUtils::FindJavaPaths() scanJavaDir(snap + dirPath); } }; +#if defined(Q_OS_LINUX) // oracle RPMs scanJavaDirs("/usr/java"); // general locations used by distro packaging @@ -437,7 +438,10 @@ QList JavaUtils::FindJavaPaths() scanJavaDirs("/opt/ibm"); // IBM Semeru Certified Edition // flatpak scanJavaDirs("/app/jdk"); - +#elif defined(Q_OS_OPENBSD) || defined(Q_OS_FREEBSD) + // ports install to /usr/local on OpenBSD & FreeBSD + scanJavaDirs("/usr/local"); +#endif auto home = qEnvironmentVariable("HOME"); // javas downloaded by IntelliJ From 303f3303f6e97ba3b39bb0f2454e1bad0002e6dc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 14 Jul 2024 00:22:27 +0000 Subject: [PATCH 32/37] 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/9f4128e00b0ae8ec65918efeba59db998750ead6?narHash=sha256-rwz8NJZV%2B387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ%3D' (2024-07-03) → 'github:NixOS/nixpkgs/7e7c39ea35c5cdd002cd4588b03a3fb9ece6fad9?narHash=sha256-EYekUHJE2gxeo2pM/zM9Wlqw1Uw2XTJXOSAO79ksc4Y%3D' (2024-07-12) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/0ff4381bbb8f7a52ca4a851660fc7a437a4c6e07?narHash=sha256-F1h%2BXIsGKT9TkGO3omxDLEb/9jOOsI6NnzsXFsZhry4%3D' (2024-06-24) → 'github:cachix/pre-commit-hooks.nix/8d6a17d0cdf411c55f12602624df6368ad86fac1?narHash=sha256-ni/87oHPZm6Gv0ECYxr1f6uxB0UKBWJ6HvS7lwLU6oY%3D' (2024-07-09) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 961cb20443..38b0d74303 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1720031269, - "narHash": "sha256-rwz8NJZV+387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ=", + "lastModified": 1720768451, + "narHash": "sha256-EYekUHJE2gxeo2pM/zM9Wlqw1Uw2XTJXOSAO79ksc4Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9f4128e00b0ae8ec65918efeba59db998750ead6", + "rev": "7e7c39ea35c5cdd002cd4588b03a3fb9ece6fad9", "type": "github" }, "original": { @@ -103,11 +103,11 @@ ] }, "locked": { - "lastModified": 1719259945, - "narHash": "sha256-F1h+XIsGKT9TkGO3omxDLEb/9jOOsI6NnzsXFsZhry4=", + "lastModified": 1720524665, + "narHash": "sha256-ni/87oHPZm6Gv0ECYxr1f6uxB0UKBWJ6HvS7lwLU6oY=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "0ff4381bbb8f7a52ca4a851660fc7a437a4c6e07", + "rev": "8d6a17d0cdf411c55f12602624df6368ad86fac1", "type": "github" }, "original": { From 6d425717e952a179b776694ea229532fac9e3801 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 16 Jul 2024 14:06:26 +0300 Subject: [PATCH 33/37] fix a few missing help pages Signed-off-by: Trial97 --- launcher/ui/pages/global/AccountListPage.h | 2 +- launcher/ui/pages/instance/ManagedPackPage.h | 2 ++ launcher/ui/pages/instance/OtherLogsPage.h | 2 +- launcher/ui/pages/instance/ShaderPackPage.h | 2 +- launcher/ui/pages/modplatform/ResourcePackPage.h | 2 ++ launcher/ui/pages/modplatform/ShaderPackPage.h | 2 ++ launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h | 2 +- launcher/ui/pages/modplatform/legacy_ftb/Page.h | 2 +- 8 files changed, 11 insertions(+), 5 deletions(-) diff --git a/launcher/ui/pages/global/AccountListPage.h b/launcher/ui/pages/global/AccountListPage.h index dd49a95d60..4f02b7df50 100644 --- a/launcher/ui/pages/global/AccountListPage.h +++ b/launcher/ui/pages/global/AccountListPage.h @@ -66,7 +66,7 @@ class AccountListPage : public QMainWindow, public BasePage { return icon; } QString id() const override { return "accounts"; } - QString helpPage() const override { return "Getting-Started#adding-an-account"; } + QString helpPage() const override { return "/getting-started/adding-an-account"; } void retranslate() override; public slots: diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index fe5a200ded..c44f77070a 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -119,6 +119,7 @@ class ModrinthManagedPackPage final : public ManagedPackPage { void parseManagedPack() override; [[nodiscard]] QString url() const override; + [[nodiscard]] QString helpPage() const override { return "modrinth-managed-pack"; } public slots: void suggestVersion() override; @@ -142,6 +143,7 @@ class FlameManagedPackPage final : public ManagedPackPage { void parseManagedPack() override; [[nodiscard]] QString url() const override; + [[nodiscard]] QString helpPage() const override { return "curseforge-managed-pack"; } public slots: void suggestVersion() override; diff --git a/launcher/ui/pages/instance/OtherLogsPage.h b/launcher/ui/pages/instance/OtherLogsPage.h index de42f5a233..85a3a2dbc8 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 "logs"; } QString displayName() const override { return tr("Other logs"); } QIcon icon() const override { return APPLICATION->getThemedIcon("log"); } - QString helpPage() const override { return "Minecraft-Logs"; } + QString helpPage() const override { return "other-Logs"; } void retranslate() override; void openedImpl() override; diff --git a/launcher/ui/pages/instance/ShaderPackPage.h b/launcher/ui/pages/instance/ShaderPackPage.h index 7c43a37564..d134e67ad3 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.h +++ b/launcher/ui/pages/instance/ShaderPackPage.h @@ -48,7 +48,7 @@ class ShaderPackPage : public ExternalResourcesPage { 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 "Resource-packs"; } + QString helpPage() const override { return "shader-packs"; } bool shouldDisplay() const override { return true; } diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.h b/launcher/ui/pages/modplatform/ResourcePackPage.h index 6015aec0bd..440d91ab0a 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.h +++ b/launcher/ui/pages/modplatform/ResourcePackPage.h @@ -40,6 +40,8 @@ class ResourcePackResourcePage : public ResourcePage { [[nodiscard]] QMap urlHandlers() const override; + [[nodiscard]] inline auto helpPage() const -> QString override { return "resourcepack-platform"; } + protected: ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance); diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h index c29317e154..4b92c33dca 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.h +++ b/launcher/ui/pages/modplatform/ShaderPackPage.h @@ -42,6 +42,8 @@ class ShaderPackResourcePage : public ResourcePage { [[nodiscard]] QMap urlHandlers() const override; + [[nodiscard]] inline auto helpPage() const -> QString override { return "shaderpack-platform"; } + protected: ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h index 8e9661272a..00f013f6ff 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h @@ -44,7 +44,7 @@ class ImportFTBPage : public QWidget, public BasePage { QString displayName() const override { return tr("FTB App Import"); } QIcon icon() const override { return APPLICATION->getThemedIcon("ftb_logo"); } QString id() const override { return "import_ftb"; } - QString helpPage() const override { return "FTB-platform"; } + QString helpPage() const override { return "FTB-import"; } bool shouldDisplay() const override { return true; } void openedImpl() override; void retranslate() override; diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.h b/launcher/ui/pages/modplatform/legacy_ftb/Page.h index 4d317b7c0f..daef233420 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.h @@ -66,7 +66,7 @@ class Page : public QWidget, public BasePage { QString displayName() const override { return "FTB Legacy"; } QIcon icon() const override { return APPLICATION->getThemedIcon("ftb_logo"); } QString id() const override { return "legacy_ftb"; } - QString helpPage() const override { return "FTB-platform"; } + QString helpPage() const override { return "FTB-legacy"; } bool shouldDisplay() const override; void openedImpl() override; void retranslate() override; From e6019ab396ff32edb2321e8d04dc793aebaaf2e7 Mon Sep 17 00:00:00 2001 From: UnownPlain <38232575+UnownPlain@users.noreply.github.com> Date: Wed, 17 Jul 2024 23:04:52 -0400 Subject: [PATCH 34/37] Fix dead link to Modrinth authentication docs Signed-off-by: UnownPlain <38232575+UnownPlain@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 93591e4402..a7f3f3f720 100644 --- a/launcher/ui/pages/global/APIPage.ui +++ b/launcher/ui/pages/global/APIPage.ui @@ -207,7 +207,7 @@ - <html><head/><body><p>Note: you only need to set this to access private data. Read the <a href="https://docs.modrinth.com/api-spec/#section/Authentication">documentation</a> for more information.</p></body></html> + <html><head/><body><p>Note: you only need to set this to access private data. Read the <a href="https://docs.modrinth.com/#section/Authentication">documentation</a> for more information.</p></body></html> true From cb65f6dfb582847d1dc9284379b1b45ac8c53b6e Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 17 Jul 2024 23:05:45 -0700 Subject: [PATCH 35/37] fix(net/validators): ensure buffers are cleared and reset; Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/meta/BaseEntity.cpp | 12 ++++++++++-- launcher/net/ChecksumValidator.h | 6 +++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 8a99e33034..cbde3b49df 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -30,13 +30,21 @@ class ParsingValidator : public Net::Validator { virtual ~ParsingValidator(){}; public: /* methods */ - bool init(QNetworkRequest&) override { return true; } + bool init(QNetworkRequest&) override + { + m_data.clear(); + return true; + } bool write(QByteArray& data) override { this->m_data.append(data); return true; } - bool abort() override { return true; } + bool abort() override + { + m_data.clear(); + return true; + } bool validate(QNetworkReply&) override { auto fname = m_entity->localFilename(); diff --git a/launcher/net/ChecksumValidator.h b/launcher/net/ChecksumValidator.h index dfee0aee59..ab24572023 100644 --- a/launcher/net/ChecksumValidator.h +++ b/launcher/net/ChecksumValidator.h @@ -60,7 +60,11 @@ class ChecksumValidator : public Validator { return true; } - auto abort() -> bool override { return true; } + auto abort() -> bool override + { + m_checksum.reset(); + return true; + } auto validate(QNetworkReply&) -> bool override { From fb10cb5fdfe121740ce3a6c24a1c9d3ea0dd429a Mon Sep 17 00:00:00 2001 From: Ben Westover Date: Thu, 18 Jul 2024 22:08:18 -0400 Subject: [PATCH 36/37] Fix a few typos As part of packaging Prism Launcher for Debian, I have run a package linter called lintian which found a few spelling errors throughout the source. I am not a fan of contributions that only fix cosmetics like spelling errors, but Debian encourages forwarding this stuff upstream instead of letting it get fixed naturally over time. Signed-off-by: Ben Westover --- launcher/Application.cpp | 2 +- launcher/minecraft/PackProfile.cpp | 4 ++-- launcher/minecraft/ProfileUtils.cpp | 6 +++--- launcher/net/NetRequest.cpp | 2 +- launcher/settings/OverrideSetting.h | 2 +- launcher/settings/PassthroughSetting.h | 2 +- launcher/ui/pages/modplatform/flame/FlameModel.cpp | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 06fc685752..5eb1d58d5a 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -817,7 +817,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_icons.reset(new IconList(instFolders, setting->get().toString())); connect(setting.get(), &Setting::SettingChanged, [&](const Setting&, QVariant value) { m_icons->directoryChanged(value.toString()); }); - qDebug() << "<> Instance icons intialized."; + qDebug() << "<> Instance icons initialized."; } // Themes diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index 4b17cdf070..63067b1919 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -181,7 +181,7 @@ static bool loadPackProfile(PackProfile* parent, } if (!componentsFile.open(QFile::ReadOnly)) { qCritical() << "Couldn't open" << componentsFile.fileName() << " for reading:" << componentsFile.errorString(); - qWarning() << "Ignoring overriden order"; + qWarning() << "Ignoring overridden order"; return false; } @@ -190,7 +190,7 @@ static bool loadPackProfile(PackProfile* parent, QJsonDocument doc = QJsonDocument::fromJson(componentsFile.readAll(), &error); if (error.error != QJsonParseError::NoError) { qCritical() << "Couldn't parse" << componentsFile.fileName() << ":" << error.errorString(); - qWarning() << "Ignoring overriden order"; + qWarning() << "Ignoring overridden order"; return false; } diff --git a/launcher/minecraft/ProfileUtils.cpp b/launcher/minecraft/ProfileUtils.cpp index f81d6cb7f2..08ec0fac3d 100644 --- a/launcher/minecraft/ProfileUtils.cpp +++ b/launcher/minecraft/ProfileUtils.cpp @@ -57,7 +57,7 @@ bool readOverrideOrders(QString path, PatchOrder& order) } if (!orderFile.open(QFile::ReadOnly)) { qCritical() << "Couldn't open" << orderFile.fileName() << " for reading:" << orderFile.errorString(); - qWarning() << "Ignoring overriden order"; + qWarning() << "Ignoring overridden order"; return false; } @@ -66,7 +66,7 @@ bool readOverrideOrders(QString path, PatchOrder& order) QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error); if (error.error != QJsonParseError::NoError) { qCritical() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString(); - qWarning() << "Ignoring overriden order"; + qWarning() << "Ignoring overridden order"; return false; } @@ -84,7 +84,7 @@ bool readOverrideOrders(QString path, PatchOrder& order) } } catch ([[maybe_unused]] const JSONValidationError& err) { qCritical() << "Couldn't parse" << orderFile.fileName() << ": bad file format"; - qWarning() << "Ignoring overriden order"; + qWarning() << "Ignoring overridden order"; order.clear(); return false; } diff --git a/launcher/net/NetRequest.cpp b/launcher/net/NetRequest.cpp index 203f1f9504..f3dbe32d3a 100644 --- a/launcher/net/NetRequest.cpp +++ b/launcher/net/NetRequest.cpp @@ -86,7 +86,7 @@ void NetRequest::executeTask() break; case State::Inactive: case State::Failed: - emit failed("Failed to initilize sink"); + emit failed("Failed to initialize sink"); emit finished(); return; case State::AbortedByUser: diff --git a/launcher/settings/OverrideSetting.h b/launcher/settings/OverrideSetting.h index faa3e7948c..3763b57171 100644 --- a/launcher/settings/OverrideSetting.h +++ b/launcher/settings/OverrideSetting.h @@ -29,7 +29,7 @@ class OverrideSetting : public Setting { Q_OBJECT public: - explicit OverrideSetting(std::shared_ptr overriden, std::shared_ptr gate); + explicit OverrideSetting(std::shared_ptr overridden, std::shared_ptr gate); virtual QVariant defValue() const; virtual QVariant get() const; diff --git a/launcher/settings/PassthroughSetting.h b/launcher/settings/PassthroughSetting.h index c776ca951f..3f34740034 100644 --- a/launcher/settings/PassthroughSetting.h +++ b/launcher/settings/PassthroughSetting.h @@ -28,7 +28,7 @@ class PassthroughSetting : public Setting { Q_OBJECT public: - explicit PassthroughSetting(std::shared_ptr overriden, std::shared_ptr gate); + explicit PassthroughSetting(std::shared_ptr overridden, std::shared_ptr gate); virtual QVariant defValue() const; virtual QVariant get() const; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 3b266bcef9..604a9a38d5 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -172,7 +172,7 @@ void ListModel::performPaginatedSearch() callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; callbacks.on_abort = [this] { qCritical() << "Search task aborted by an unknown reason!"; - searchRequestFailed("Abborted"); + searchRequestFailed("Aborted"); }; static const FlameAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { From fc2d0134024619c84eda5649df2196e5600c3808 Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Sat, 20 Jul 2024 01:50:30 +0300 Subject: [PATCH 37/37] ui: swap timeoutSecondsLabel and numberOfManualRetriesLabel order fixes: 7a200a337f08cfa1e32102594958f10cb7f000c6 conflicted with 6078a771c18fd749f38d7c1a2f80ed3c7ec7ad28 Signed-off-by: Edgars Cirulis --- launcher/ui/pages/global/LauncherPage.ui | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index b3387ba026..72039488bc 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -291,33 +291,33 @@ - - - Seconds to wait until the requests are terminated - + - Timeout for HTTP requests + Number of manual retries - - - s + + + 0 - + + + Seconds to wait until the requests are terminated + - Number of manual retries + Timeout for HTTP requests - - - 0 + + + s