From f7f7bc68653a3bfbfd9a571624582d45ef5e224b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 15 Aug 2023 20:52:17 +0300 Subject: [PATCH 01/26] Removed update disabled warning Signed-off-by: Trial97 --- launcher/minecraft/mod/ModFolderModel.cpp | 5 ++++- launcher/modplatform/CheckUpdateTask.h | 11 ++++++++++- launcher/modplatform/flame/FlameCheckUpdate.cpp | 7 +------ launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp | 7 +------ launcher/ui/dialogs/ModUpdateDialog.cpp | 4 +--- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 280e70d7b..1b96590a4 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -196,7 +196,10 @@ Task* ModFolderModel::createParseTask(Resource& resource) bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadata) { for (auto mod : allMods()) { - if (mod->fileinfo().fileName() == filename) { + auto modfilename = mod->fileinfo().fileName(); + if (!mod->enabled() && modfilename.endsWith(".disabled")) + modfilename.chop(9); + if (modfilename == filename) { auto index_dir = indexDir(); mod->destroy(index_dir, preserve_metadata, false); diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index 6d968ea48..6afa9c290 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -24,6 +24,7 @@ class CheckUpdateTask : public Task { QString old_version; QString new_version; QString changelog; + bool enabled; ModPlatform::ResourceProvider provider; shared_qobject_ptr download; @@ -33,9 +34,17 @@ class CheckUpdateTask : public Task { QString old_v, QString new_v, QString changelog, + bool enabled, ModPlatform::ResourceProvider p, shared_qobject_ptr t) - : name(name), old_hash(old_h), old_version(old_v), new_version(new_v), changelog(changelog), provider(p), download(t) + : name(name) + , old_hash(old_h) + , old_version(old_v) + , new_version(new_v) + , changelog(changelog) + , enabled(enabled) + , provider(p) + , download(t) {} }; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index e10fedc3c..79ae82e69 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -124,11 +124,6 @@ void FlameCheckUpdate::executeTask() int i = 0; for (auto* mod : m_mods) { - if (!mod->enabled()) { - emit checkFailed(mod, tr("Disabled mods won't be updated, to prevent mod duplication issues!")); - continue; - } - setStatus(tr("Getting API response from CurseForge for '%1'...").arg(mod->name())); setProgress(i++, m_mods.size()); @@ -176,7 +171,7 @@ void FlameCheckUpdate::executeTask() auto download_task = makeShared(pack, latest_ver, m_mods_folder); m_updatable.emplace_back(pack->name, mod->metadata()->hash, old_version, latest_ver.version, - api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()), + api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()), mod->enabled(), ModPlatform::ResourceProvider::FLAME, download_task); } } diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index a7c22832a..41eac6415 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -41,11 +41,6 @@ void ModrinthCheckUpdate::executeTask() ConcurrentTask hashing_task(this, "MakeModrinthHashesTask", 10); for (auto* mod : m_mods) { - if (!mod->enabled()) { - emit checkFailed(mod, tr("Disabled mods won't be updated, to prevent mod duplication issues!")); - continue; - } - auto hash = mod->metadata()->hash; // Sadly the API can only handle one hash type per call, se we @@ -163,7 +158,7 @@ void ModrinthCheckUpdate::executeTask() 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.changelog, - ModPlatform::ResourceProvider::MODRINTH, download_task); + mod->enabled(), ModPlatform::ResourceProvider::MODRINTH, download_task); } } } catch (Json::JsonException& e) { diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 0af1ec59b..639887a5d 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -5,8 +5,6 @@ #include "ScrollMessageBox.h" #include "ui_ReviewMessageBox.h" -#include "FileSystem.h" -#include "Json.h" #include "Markdown.h" #include "tasks/ConcurrentTask.h" @@ -351,7 +349,7 @@ void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::R void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info) { auto item_top = new QTreeWidgetItem(ui->modTreeWidget); - item_top->setCheckState(0, Qt::CheckState::Checked); + item_top->setCheckState(0, info.enabled ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); item_top->setText(0, info.name); item_top->setExpanded(true); From c41c39b5d86b168a189a82460fc6edb7873cfa6e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 15 Aug 2023 23:55:09 +0300 Subject: [PATCH 02/26] cleanup the mod name checking Signed-off-by: Trial97 --- launcher/minecraft/mod/ModFolderModel.cpp | 5 +---- launcher/minecraft/mod/Resource.cpp | 8 ++++++++ launcher/minecraft/mod/Resource.h | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 1b96590a4..1f10a5a2f 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -196,10 +196,7 @@ Task* ModFolderModel::createParseTask(Resource& resource) bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadata) { for (auto mod : allMods()) { - auto modfilename = mod->fileinfo().fileName(); - if (!mod->enabled() && modfilename.endsWith(".disabled")) - modfilename.chop(9); - if (modfilename == filename) { + if (mod->getOriginalFileName() == filename) { auto index_dir = indexDir(); mod->destroy(index_dir, preserve_metadata, false); diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index da806f0f4..6a60473fb 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -169,3 +169,11 @@ bool Resource::isMoreThanOneHardLink() const { return FS::hardLinkCount(m_file_info.absoluteFilePath()) > 1; } + +auto Resource::getOriginalFileName() const -> QString +{ + auto fileName = m_file_info.fileName(); + if (!m_enabled) + fileName.chop(9); + return fileName; +} \ No newline at end of file diff --git a/launcher/minecraft/mod/Resource.h b/launcher/minecraft/mod/Resource.h index c1ed49461..f0d34705c 100644 --- a/launcher/minecraft/mod/Resource.h +++ b/launcher/minecraft/mod/Resource.h @@ -45,6 +45,7 @@ class Resource : public QObject { [[nodiscard]] auto internal_id() const -> QString { return m_internal_id; } [[nodiscard]] auto type() const -> ResourceType { return m_type; } [[nodiscard]] bool enabled() const { return m_enabled; } + [[nodiscard]] auto getOriginalFileName() const -> QString; [[nodiscard]] virtual auto name() const -> QString { return m_name; } [[nodiscard]] virtual bool valid() const { return m_type != ResourceType::UNKNOWN; } From 0ff98c5876f73556e328cba352fb12566f889e08 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 15 Oct 2023 21:22:59 +0300 Subject: [PATCH 03/26] allways enable dependencies Signed-off-by: Trial97 --- launcher/ui/dialogs/ModUpdateDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index a0c2f2f44..9499378a5 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -220,8 +220,8 @@ void ModUpdateDialog::checkCandidates() changelog = api.getModFileChangelog(dep->version.addonId.toInt(), dep->version.fileId.toInt()); auto download_task = makeShared(dep->pack, dep->version, m_mod_model); CheckUpdateTask::UpdatableMod updatable = { - dep->pack->name, dep->version.hash, "", dep->version.version, dep->version.version_type, - changelog, dep->pack->provider, download_task + dep->pack->name, dep->version.hash, "", dep->version.version, dep->version.version_type, changelog, true, + dep->pack->provider, download_task }; appendMod(updatable, getRequiredBy.value(dep->version.addonId.toString())); From 63a458ca0c9dbad02dd4218c9eed35bb9af7b6e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 28 Jun 2024 21:48:40 +0000 Subject: [PATCH 04/26] Update DeterminateSystems/update-flake-lock action to v23 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 2226d0710..e1ab2e86e 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - - uses: DeterminateSystems/update-flake-lock@v22 + - uses: DeterminateSystems/update-flake-lock@v23 with: commit-msg: "chore(nix): update lockfile" pr-title: "chore(nix): update lockfile" From c07260e836b2e2884e6694f99882d6eebbc7c130 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 7 Jul 2024 02:49:27 +0300 Subject: [PATCH 05/26] remove duplicate code from net folder Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 1 - .../minecraft/auth/steps/EntitlementsStep.cpp | 4 +- .../auth/steps/LauncherLoginStep.cpp | 4 +- .../auth/steps/MSADeviceCodeStep.cpp | 6 +-- .../auth/steps/MinecraftProfileStep.cpp | 4 +- .../auth/steps/XboxAuthorizationStep.cpp | 4 +- .../minecraft/auth/steps/XboxProfileStep.cpp | 4 +- .../minecraft/auth/steps/XboxUserStep.cpp | 4 +- launcher/minecraft/skins/CapeChange.cpp | 16 +++----- launcher/minecraft/skins/CapeChange.h | 4 +- launcher/minecraft/skins/SkinDelete.cpp | 16 +++----- launcher/minecraft/skins/SkinDelete.h | 6 +-- launcher/minecraft/skins/SkinUpload.cpp | 16 +++----- launcher/minecraft/skins/SkinUpload.h | 4 +- .../modplatform/flame/FileResolvingTask.cpp | 4 +- launcher/net/ApiDownload.cpp | 39 +++++-------------- launcher/net/ApiDownload.h | 16 +++----- launcher/net/ApiUpload.cpp | 14 ++----- launcher/net/ApiUpload.h | 10 +---- launcher/net/NetRequest.cpp | 2 - launcher/net/NetRequest.h | 2 - launcher/net/RawHeaderProxy.h | 4 +- launcher/net/StaticHeaderProxy.h | 39 ------------------- launcher/screenshots/ImgurAlbumCreation.cpp | 16 +++----- launcher/screenshots/ImgurAlbumCreation.h | 2 - launcher/screenshots/ImgurUpload.cpp | 12 ++---- launcher/screenshots/ImgurUpload.h | 2 - launcher/ui/dialogs/ProfileSetupDialog.cpp | 6 +-- 28 files changed, 72 insertions(+), 189 deletions(-) delete mode 100644 launcher/net/StaticHeaderProxy.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 366719dec..0208c5ec3 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -138,7 +138,6 @@ set(NET_SOURCES net/HeaderProxy.h net/RawHeaderProxy.h net/ApiHeaderProxy.h - net/StaticHeaderProxy.h net/ApiDownload.h net/ApiDownload.cpp net/ApiUpload.cpp diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.cpp b/launcher/minecraft/auth/steps/EntitlementsStep.cpp index 19cbe6898..24b9677cf 100644 --- a/launcher/minecraft/auth/steps/EntitlementsStep.cpp +++ b/launcher/minecraft/auth/steps/EntitlementsStep.cpp @@ -10,7 +10,7 @@ #include "Logging.h" #include "minecraft/auth/Parsers.h" #include "net/Download.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" #include "tasks/Task.h" EntitlementsStep::EntitlementsStep(AccountData* data) : AuthStep(data) {} @@ -32,7 +32,7 @@ void EntitlementsStep::perform() m_response.reset(new QByteArray()); m_task = Net::Download::makeByteArray(url, m_response); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_task.get(), &Task::finished, this, &EntitlementsStep::onRequestDone); diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp index d72346c74..3f5a4e8cc 100644 --- a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp +++ b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp @@ -7,7 +7,7 @@ #include "Logging.h" #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" #include "net/Upload.h" LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {} @@ -38,7 +38,7 @@ 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_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_task.get(), &Task::finished, this, &LauncherLoginStep::onRequestDone); diff --git a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp index 7df93d04d..19cce2a81 100644 --- a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp +++ b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp @@ -40,7 +40,7 @@ #include "Application.h" #include "Json.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" // https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-device-code MSADeviceCodeStep::MSADeviceCodeStep(AccountData* data) : AuthStep(data) @@ -68,7 +68,7 @@ void MSADeviceCodeStep::perform() }; m_response.reset(new QByteArray()); m_task = Net::Upload::makeByteArray(url, m_response, payload); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_task.get(), &Task::finished, this, &MSADeviceCodeStep::deviceAutorizationFinished); @@ -180,7 +180,7 @@ void MSADeviceCodeStep::authenticateUser() }; m_response.reset(new QByteArray()); m_task = Net::Upload::makeByteArray(url, m_response, payload); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_task.get(), &Task::finished, this, &MSADeviceCodeStep::authenticationFinished); diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp index aef6f43af..145eabec2 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp @@ -5,7 +5,7 @@ #include "Application.h" #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" MinecraftProfileStep::MinecraftProfileStep(AccountData* data) : AuthStep(data) {} @@ -23,7 +23,7 @@ void MinecraftProfileStep::perform() m_response.reset(new QByteArray()); m_task = Net::Download::makeByteArray(url, m_response); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_task.get(), &Task::finished, this, &MinecraftProfileStep::onRequestDone); diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp index f07220986..f5a890dc4 100644 --- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp +++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp @@ -8,7 +8,7 @@ #include "Logging.h" #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" #include "net/Upload.h" XboxAuthorizationStep::XboxAuthorizationStep(AccountData* data, Token* token, QString relyingParty, QString authorizationKind) @@ -43,7 +43,7 @@ void XboxAuthorizationStep::perform() }; 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_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_task.get(), &Task::finished, this, &XboxAuthorizationStep::onRequestDone); diff --git a/launcher/minecraft/auth/steps/XboxProfileStep.cpp b/launcher/minecraft/auth/steps/XboxProfileStep.cpp index 440a4657c..5777bd2e4 100644 --- a/launcher/minecraft/auth/steps/XboxProfileStep.cpp +++ b/launcher/minecraft/auth/steps/XboxProfileStep.cpp @@ -6,7 +6,7 @@ #include "Application.h" #include "Logging.h" #include "net/NetUtils.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" XboxProfileStep::XboxProfileStep(AccountData* data) : AuthStep(data) {} @@ -35,7 +35,7 @@ void XboxProfileStep::perform() m_response.reset(new QByteArray()); m_task = Net::Download::makeByteArray(url, m_response); - m_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_task.get(), &Task::finished, this, &XboxProfileStep::onRequestDone); diff --git a/launcher/minecraft/auth/steps/XboxUserStep.cpp b/launcher/minecraft/auth/steps/XboxUserStep.cpp index c9453dba1..561fa0767 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.cpp +++ b/launcher/minecraft/auth/steps/XboxUserStep.cpp @@ -5,7 +5,7 @@ #include "Application.h" #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" XboxUserStep::XboxUserStep(AccountData* data) : AuthStep(data) {} @@ -39,7 +39,7 @@ void XboxUserStep::perform() }; 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_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_task.get(), &Task::finished, this, &XboxUserStep::onRequestDone); diff --git a/launcher/minecraft/skins/CapeChange.cpp b/launcher/minecraft/skins/CapeChange.cpp index 4db28e245..abbaa0b67 100644 --- a/launcher/minecraft/skins/CapeChange.cpp +++ b/launcher/minecraft/skins/CapeChange.cpp @@ -39,9 +39,9 @@ #include #include "net/ByteArraySink.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" -CapeChange::CapeChange(QString token, QString cape) : NetRequest(), m_capeId(cape), m_token(token) +CapeChange::CapeChange(QString cape) : NetRequest(), m_capeId(cape) { logCat = taskMCSkinsLogC; } @@ -57,18 +57,14 @@ QNetworkReply* CapeChange::getReply(QNetworkRequest& request) } } -void CapeChange::init() -{ - addHeaderProxy(new Net::StaticHeaderProxy(QList{ - { "Authorization", QString("Bearer %1").arg(m_token).toLocal8Bit() }, - })); -} - CapeChange::Ptr CapeChange::make(QString token, QString capeId) { - auto up = makeShared(token, capeId); + auto up = makeShared(capeId); up->m_url = QUrl("https://api.minecraftservices.com/minecraft/profile/capes/active"); up->setObjectName(QString("BYTES:") + up->m_url.toString()); up->m_sink.reset(new Net::ByteArraySink(std::make_shared())); + up->addHeaderProxy(new Net::RawHeaderProxy(QList{ + { "Authorization", QString("Bearer %1").arg(token).toLocal8Bit() }, + })); return up; } diff --git a/launcher/minecraft/skins/CapeChange.h b/launcher/minecraft/skins/CapeChange.h index bcafcde87..2be904f4d 100644 --- a/launcher/minecraft/skins/CapeChange.h +++ b/launcher/minecraft/skins/CapeChange.h @@ -24,16 +24,14 @@ class CapeChange : public Net::NetRequest { Q_OBJECT public: using Ptr = shared_qobject_ptr; - CapeChange(QString token, QString capeId); + CapeChange(QString capeId); virtual ~CapeChange() = default; static CapeChange::Ptr make(QString token, QString capeId); - void init() override; protected: virtual QNetworkReply* getReply(QNetworkRequest&) override; private: QString m_capeId; - QString m_token; }; diff --git a/launcher/minecraft/skins/SkinDelete.cpp b/launcher/minecraft/skins/SkinDelete.cpp index 3c50cf313..94aca62ca 100644 --- a/launcher/minecraft/skins/SkinDelete.cpp +++ b/launcher/minecraft/skins/SkinDelete.cpp @@ -37,9 +37,9 @@ #include "SkinDelete.h" #include "net/ByteArraySink.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" -SkinDelete::SkinDelete(QString token) : NetRequest(), m_token(token) +SkinDelete::SkinDelete() : NetRequest() { logCat = taskMCSkinsLogC; } @@ -50,17 +50,13 @@ QNetworkReply* SkinDelete::getReply(QNetworkRequest& request) return m_network->deleteResource(request); } -void SkinDelete::init() -{ - addHeaderProxy(new Net::StaticHeaderProxy(QList{ - { "Authorization", QString("Bearer %1").arg(m_token).toLocal8Bit() }, - })); -} - SkinDelete::Ptr SkinDelete::make(QString token) { - auto up = makeShared(token); + auto up = makeShared(); up->m_url = QUrl("https://api.minecraftservices.com/minecraft/profile/skins/active"); up->m_sink.reset(new Net::ByteArraySink(std::make_shared())); + up->addHeaderProxy(new Net::RawHeaderProxy(QList{ + { "Authorization", QString("Bearer %1").arg(token).toLocal8Bit() }, + })); return up; } diff --git a/launcher/minecraft/skins/SkinDelete.h b/launcher/minecraft/skins/SkinDelete.h index 5d02e0cc4..d6a68d22c 100644 --- a/launcher/minecraft/skins/SkinDelete.h +++ b/launcher/minecraft/skins/SkinDelete.h @@ -24,15 +24,11 @@ class SkinDelete : public Net::NetRequest { Q_OBJECT public: using Ptr = shared_qobject_ptr; - SkinDelete(QString token); + SkinDelete(); virtual ~SkinDelete() = default; static SkinDelete::Ptr make(QString token); - void init() override; protected: virtual QNetworkReply* getReply(QNetworkRequest&) override; - - private: - QString m_token; }; diff --git a/launcher/minecraft/skins/SkinUpload.cpp b/launcher/minecraft/skins/SkinUpload.cpp index dc1bc0bf9..ccc29d281 100644 --- a/launcher/minecraft/skins/SkinUpload.cpp +++ b/launcher/minecraft/skins/SkinUpload.cpp @@ -40,9 +40,9 @@ #include "FileSystem.h" #include "net/ByteArraySink.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" -SkinUpload::SkinUpload(QString token, QString path, QString variant) : NetRequest(), m_token(token), m_path(path), m_variant(variant) +SkinUpload::SkinUpload(QString path, QString variant) : NetRequest(), m_path(path), m_variant(variant) { logCat = taskMCSkinsLogC; } @@ -67,18 +67,14 @@ QNetworkReply* SkinUpload::getReply(QNetworkRequest& request) return m_network->post(request, multiPart); } -void SkinUpload::init() -{ - addHeaderProxy(new Net::StaticHeaderProxy(QList{ - { "Authorization", QString("Bearer %1").arg(m_token).toLocal8Bit() }, - })); -} - SkinUpload::Ptr SkinUpload::make(QString token, QString path, QString variant) { - auto up = makeShared(token, path, variant); + auto up = makeShared(path, variant); up->m_url = QUrl("https://api.minecraftservices.com/minecraft/profile/skins"); up->setObjectName(QString("BYTES:") + up->m_url.toString()); up->m_sink.reset(new Net::ByteArraySink(std::make_shared())); + up->addHeaderProxy(new Net::RawHeaderProxy(QList{ + { "Authorization", QString("Bearer %1").arg(token).toLocal8Bit() }, + })); return up; } diff --git a/launcher/minecraft/skins/SkinUpload.h b/launcher/minecraft/skins/SkinUpload.h index f24cef5a2..c1a4930b7 100644 --- a/launcher/minecraft/skins/SkinUpload.h +++ b/launcher/minecraft/skins/SkinUpload.h @@ -26,17 +26,15 @@ class SkinUpload : public Net::NetRequest { using Ptr = shared_qobject_ptr; // Note this class takes ownership of the file. - SkinUpload(QString token, QString path, QString variant); + SkinUpload(QString path, QString variant); virtual ~SkinUpload() = default; static SkinUpload::Ptr make(QString token, QString path, QString variant); - void init() override; protected: virtual QNetworkReply* getReply(QNetworkRequest&) override; private: - QString m_token; QString m_path; QString m_variant; }; diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 8d23896d9..f81452c96 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -103,7 +103,7 @@ void Flame::FileResolvingTask::netJobFinished() auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash); auto output = std::make_shared(); auto dl = Net::ApiDownload::makeByteArray(QUrl(url), output); - QObject::connect(dl.get(), &Net::ApiDownload::succeeded, [&out]() { out.resolved = true; }); + QObject::connect(dl.get(), &Task::succeeded, [&out]() { out.resolved = true; }); m_checkJob->addNetAction(dl); blockedProjects.insert(&out, output); @@ -175,7 +175,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId); auto dl = Net::ApiDownload::makeByteArray(url, output); qDebug() << "Fetching url slug for file:" << mod->fileName; - QObject::connect(dl.get(), &Net::ApiDownload::succeeded, [block, index, output]() { + QObject::connect(dl.get(), &Task::succeeded, [block, index, output]() { auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done auto json = QJsonDocument::fromJson(*output); auto base = diff --git a/launcher/net/ApiDownload.cpp b/launcher/net/ApiDownload.cpp index 8768b63f8..78eb1f851 100644 --- a/launcher/net/ApiDownload.cpp +++ b/launcher/net/ApiDownload.cpp @@ -18,48 +18,29 @@ */ #include "net/ApiDownload.h" -#include "ByteArraySink.h" -#include "ChecksumValidator.h" -#include "MetaCacheSink.h" +#include "net/ApiHeaderProxy.h" namespace Net { -auto ApiDownload::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Download::Ptr +Download::Ptr ApiDownload::makeCached(QUrl url, MetaEntryPtr entry, Download::Options options) { - auto dl = makeShared(); - dl->m_url = url; - dl->setObjectName(QString("CACHE:") + url.toString()); - dl->m_options = options; - auto md5Node = new ChecksumValidator(QCryptographicHash::Md5); - auto cachedNode = new MetaCacheSink(entry, md5Node, options.testFlag(Option::MakeEternal)); - dl->m_sink.reset(cachedNode); + auto dl = Download::makeCached(url, entry, options); + dl->addHeaderProxy(new ApiHeaderProxy()); return dl; } -auto ApiDownload::makeByteArray(QUrl url, std::shared_ptr output, Options options) -> Download::Ptr +Download::Ptr ApiDownload::makeByteArray(QUrl url, std::shared_ptr output, Download::Options options) { - auto dl = makeShared(); - dl->m_url = url; - dl->setObjectName(QString("BYTES:") + url.toString()); - dl->m_options = options; - dl->m_sink.reset(new ByteArraySink(output)); + auto dl = Download::makeByteArray(url, output, options); + dl->addHeaderProxy(new ApiHeaderProxy()); return dl; } -auto ApiDownload::makeFile(QUrl url, QString path, Options options) -> Download::Ptr +Download::Ptr ApiDownload::makeFile(QUrl url, QString path, Download::Options options) { - auto dl = makeShared(); - dl->m_url = url; - dl->setObjectName(QString("FILE:") + url.toString()); - dl->m_options = options; - dl->m_sink.reset(new FileSink(path)); + auto dl = Download::makeFile(url, path, options); + dl->addHeaderProxy(new ApiHeaderProxy()); return dl; } -void ApiDownload::init() -{ - qDebug() << "Setting up api download"; - auto api_headers = new ApiHeaderProxy(); - addHeaderProxy(api_headers); -} } // namespace Net diff --git a/launcher/net/ApiDownload.h b/launcher/net/ApiDownload.h index 638c94e11..842c25c56 100644 --- a/launcher/net/ApiDownload.h +++ b/launcher/net/ApiDownload.h @@ -19,20 +19,14 @@ #pragma once -#include "ApiHeaderProxy.h" #include "Download.h" namespace Net { -class ApiDownload : public Download { - public: - virtual ~ApiDownload() = default; - - static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; - static auto makeByteArray(QUrl url, std::shared_ptr output, Options options = Option::NoOptions) -> Download::Ptr; - static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; - - void init() override; -}; +namespace ApiDownload { +Download::Ptr makeCached(QUrl url, MetaEntryPtr entry, Download::Options options = Download::Option::NoOptions); +Download::Ptr makeByteArray(QUrl url, std::shared_ptr output, Download::Options options = Download::Option::NoOptions); +Download::Ptr makeFile(QUrl url, QString path, Download::Options options = Download::Option::NoOptions); +}; // namespace ApiDownload } // namespace Net diff --git a/launcher/net/ApiUpload.cpp b/launcher/net/ApiUpload.cpp index 505cbd9f9..a2b8f357b 100644 --- a/launcher/net/ApiUpload.cpp +++ b/launcher/net/ApiUpload.cpp @@ -18,23 +18,15 @@ */ #include "net/ApiUpload.h" -#include "ByteArraySink.h" +#include "net/ApiHeaderProxy.h" namespace Net { Upload::Ptr ApiUpload::makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data) { - auto up = makeShared(); - up->m_url = std::move(url); - up->m_sink.reset(new ByteArraySink(output)); - up->m_post_data = std::move(m_post_data); + auto up = Upload::makeByteArray(url, output, m_post_data); + up->addHeaderProxy(new ApiHeaderProxy()); return up; } -void ApiUpload::init() -{ - qDebug() << "Setting up api upload"; - auto api_headers = new ApiHeaderProxy(); - addHeaderProxy(api_headers); -} } // namespace Net diff --git a/launcher/net/ApiUpload.h b/launcher/net/ApiUpload.h index b12842b05..674a3b93f 100644 --- a/launcher/net/ApiUpload.h +++ b/launcher/net/ApiUpload.h @@ -19,18 +19,12 @@ #pragma once -#include "ApiHeaderProxy.h" #include "Upload.h" namespace Net { -class ApiUpload : public Upload { - public: - virtual ~ApiUpload() = default; - - static Upload::Ptr makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data); - - void init() override; +namespace ApiUpload { +Upload::Ptr makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data); }; } // namespace Net diff --git a/launcher/net/NetRequest.cpp b/launcher/net/NetRequest.cpp index 203f1f950..e8e858350 100644 --- a/launcher/net/NetRequest.cpp +++ b/launcher/net/NetRequest.cpp @@ -62,8 +62,6 @@ void NetRequest::addValidator(Validator* v) void NetRequest::executeTask() { - init(); - setStatus(tr("Requesting %1").arg(StringUtils::truncateUrlHumanFriendly(m_url, 80))); if (getState() == Task::State::AbortedByUser) { diff --git a/launcher/net/NetRequest.h b/launcher/net/NetRequest.h index 0cd6ceabc..6b3f643d6 100644 --- a/launcher/net/NetRequest.h +++ b/launcher/net/NetRequest.h @@ -72,8 +72,6 @@ class NetRequest : public Task { void setNetwork(shared_qobject_ptr network) { m_network = network; } void addHeaderProxy(Net::HeaderProxy* proxy) { m_headerProxies.push_back(std::shared_ptr(proxy)); } - virtual void init() {} - QUrl url() const; void setUrl(QUrl url) { m_url = url; } int replyStatusCode() const; diff --git a/launcher/net/RawHeaderProxy.h b/launcher/net/RawHeaderProxy.h index 09b3d4d02..682cc9e4d 100644 --- a/launcher/net/RawHeaderProxy.h +++ b/launcher/net/RawHeaderProxy.h @@ -4,6 +4,7 @@ * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +28,7 @@ namespace Net { class RawHeaderProxy : public HeaderProxy { public: - RawHeaderProxy() : HeaderProxy() {} + RawHeaderProxy(QList headers = {}) : HeaderProxy(), m_headers(headers) {}; virtual ~RawHeaderProxy() = default; public: @@ -36,6 +37,7 @@ class RawHeaderProxy : public HeaderProxy { void addHeader(const HeaderPair& header) { m_headers.append(header); } void addHeader(const QByteArray& headerName, const QByteArray& headerValue) { m_headers.append({ headerName, headerValue }); } void addHeaders(const QList& headers) { m_headers.append(headers); } + void setHeaders(QList headers) { m_headers = headers; }; private: QList m_headers; diff --git a/launcher/net/StaticHeaderProxy.h b/launcher/net/StaticHeaderProxy.h deleted file mode 100644 index 73678c026..000000000 --- a/launcher/net/StaticHeaderProxy.h +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#pragma once - -#include "net/HeaderProxy.h" - -namespace Net { - -class StaticHeaderProxy : public HeaderProxy { - public: - StaticHeaderProxy(QList hdrs = {}) : HeaderProxy(), m_hdrs(hdrs) {}; - virtual ~StaticHeaderProxy() = default; - - public: - virtual QList headers(const QNetworkRequest&) const override { return m_hdrs; }; - void setHeaders(QList hdrs) { m_hdrs = hdrs; }; - - private: - QList m_hdrs; -}; - -} // namespace Net diff --git a/launcher/screenshots/ImgurAlbumCreation.cpp b/launcher/screenshots/ImgurAlbumCreation.cpp index c63c8b39b..8eecc2aaa 100644 --- a/launcher/screenshots/ImgurAlbumCreation.cpp +++ b/launcher/screenshots/ImgurAlbumCreation.cpp @@ -46,7 +46,7 @@ #include #include "BuildConfig.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" Net::NetRequest::Ptr ImgurAlbumCreation::make(std::shared_ptr output, QList screenshots) { @@ -54,6 +54,10 @@ Net::NetRequest::Ptr ImgurAlbumCreation::make(std::shared_ptrm_url = BuildConfig.IMGUR_BASE_URL + "album"; up->m_sink.reset(new Sink(output)); up->m_screenshots = screenshots; + up->addHeaderProxy(new Net::RawHeaderProxy( + QList{ { "Content-Type", "application/x-www-form-urlencoded" }, + { "Authorization", QString("Client-ID %1").arg(BuildConfig.IMGUR_CLIENT_ID).toUtf8() }, + { "Accept", "application/json" } })); return up; } @@ -67,16 +71,6 @@ QNetworkReply* ImgurAlbumCreation::getReply(QNetworkRequest& request) return m_network->post(request, data); }; -void ImgurAlbumCreation::init() -{ - qDebug() << "Setting up imgur upload"; - auto api_headers = new Net::StaticHeaderProxy( - QList{ { "Content-Type", "application/x-www-form-urlencoded" }, - { "Authorization", QString("Client-ID %1").arg(BuildConfig.IMGUR_CLIENT_ID).toUtf8() }, - { "Accept", "application/json" } }); - addHeaderProxy(api_headers); -} - auto ImgurAlbumCreation::Sink::init(QNetworkRequest& request) -> Task::State { m_output.clear(); diff --git a/launcher/screenshots/ImgurAlbumCreation.h b/launcher/screenshots/ImgurAlbumCreation.h index ecb225394..f10409b20 100644 --- a/launcher/screenshots/ImgurAlbumCreation.h +++ b/launcher/screenshots/ImgurAlbumCreation.h @@ -67,8 +67,6 @@ class ImgurAlbumCreation : public Net::NetRequest { static NetRequest::Ptr make(std::shared_ptr output, QList screenshots); QNetworkReply* getReply(QNetworkRequest& request) override; - void init() override; - private: QList m_screenshots; }; diff --git a/launcher/screenshots/ImgurUpload.cpp b/launcher/screenshots/ImgurUpload.cpp index 941b92ce6..78b50f52e 100644 --- a/launcher/screenshots/ImgurUpload.cpp +++ b/launcher/screenshots/ImgurUpload.cpp @@ -36,7 +36,7 @@ #include "ImgurUpload.h" #include "BuildConfig.h" -#include "net/StaticHeaderProxy.h" +#include "net/RawHeaderProxy.h" #include #include @@ -47,14 +47,6 @@ #include #include -void ImgurUpload::init() -{ - qDebug() << "Setting up imgur upload"; - auto api_headers = new Net::StaticHeaderProxy(QList{ - { "Authorization", QString("Client-ID %1").arg(BuildConfig.IMGUR_CLIENT_ID).toUtf8() }, { "Accept", "application/json" } }); - addHeaderProxy(api_headers); -} - QNetworkReply* ImgurUpload::getReply(QNetworkRequest& request) { auto file = new QFile(m_fileInfo.absoluteFilePath(), this); @@ -125,5 +117,7 @@ Net::NetRequest::Ptr ImgurUpload::make(ScreenShot::Ptr m_shot) auto up = makeShared(m_shot->m_file); up->m_url = std::move(BuildConfig.IMGUR_BASE_URL + "image"); up->m_sink.reset(new Sink(m_shot)); + up->addHeaderProxy(new Net::RawHeaderProxy(QList{ + { "Authorization", QString("Client-ID %1").arg(BuildConfig.IMGUR_CLIENT_ID).toUtf8() }, { "Accept", "application/json" } })); return up; } diff --git a/launcher/screenshots/ImgurUpload.h b/launcher/screenshots/ImgurUpload.h index 5a58ad2b5..f4f71859d 100644 --- a/launcher/screenshots/ImgurUpload.h +++ b/launcher/screenshots/ImgurUpload.h @@ -62,8 +62,6 @@ class ImgurUpload : public Net::NetRequest { static NetRequest::Ptr make(ScreenShot::Ptr m_shot); - void init() override; - private: virtual QNetworkReply* getReply(QNetworkRequest&) override; const QFileInfo m_fileInfo; diff --git a/launcher/ui/dialogs/ProfileSetupDialog.cpp b/launcher/ui/dialogs/ProfileSetupDialog.cpp index c5d4c2621..385094e23 100644 --- a/launcher/ui/dialogs/ProfileSetupDialog.cpp +++ b/launcher/ui/dialogs/ProfileSetupDialog.cpp @@ -34,6 +34,7 @@ */ #include "ProfileSetupDialog.h" +#include "net/RawHeaderProxy.h" #include "ui_ProfileSetupDialog.h" #include @@ -46,7 +47,6 @@ #include #include "minecraft/auth/Parsers.h" -#include "net/StaticHeaderProxy.h" #include "net/Upload.h" ProfileSetupDialog::ProfileSetupDialog(MinecraftAccountPtr accountToSetup, QWidget* parent) @@ -160,7 +160,7 @@ void ProfileSetupDialog::checkName(const QString& name) if (m_check_task) disconnect(m_check_task.get(), nullptr, this, nullptr); m_check_task = Net::Download::makeByteArray(url, m_check_response); - m_check_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_check_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_check_task.get(), &Task::finished, this, &ProfileSetupDialog::checkFinished); @@ -204,7 +204,7 @@ void ProfileSetupDialog::setupProfile(const QString& profileName) m_profile_response.reset(new QByteArray()); m_profile_task = Net::Upload::makeByteArray(url, m_profile_response, payloadTemplate.arg(profileName).toUtf8()); - m_profile_task->addHeaderProxy(new Net::StaticHeaderProxy(headers)); + m_profile_task->addHeaderProxy(new Net::RawHeaderProxy(headers)); connect(m_profile_task.get(), &Task::finished, this, &ProfileSetupDialog::setupProfileFinished); From e5b1fa1e3a2eecd4849dd7f77e93fb8d1b4ee44d Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Tue, 9 Jul 2024 02:21:50 +0300 Subject: [PATCH 06/26] readme: build instructions Signed-off-by: Edgars Cirulis --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b32132d49..9c4909509 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,12 @@ The translation effort for Prism Launcher is hosted on [Weblate](https://hosted. ## Building -If you want to build Prism Launcher yourself, check the [Build Instructions](https://prismlauncher.org/wiki/development/build-instructions/). +If you want to build Prism Launcher yourself, check the build instructions: + +- [Windows](https://prismlauncher.org/wiki/development/build-instructions/windows/) +- [Linux](https://prismlauncher.org/wiki/development/build-instructions/linux/) +- [MacOS](https://prismlauncher.org/wiki/development/build-instructions/macos/) +- [OpenBSD](https://prismlauncher.org/wiki/development/build-instructions/openbsd/) ## Sponsors & Partners From 3076e5b961d2e0a24ff8fec9d0d1c1e1b95e3cd2 Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Tue, 9 Jul 2024 22:21:13 +0300 Subject: [PATCH 07/26] remove useless BUILD.md orphaned file Signed-off-by: Edgars Cirulis --- BUILD.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 BUILD.md diff --git a/BUILD.md b/BUILD.md deleted file mode 100644 index a139039df..000000000 --- a/BUILD.md +++ /dev/null @@ -1,3 +0,0 @@ -# Build Instructions - -Full build instructions are available on [the website](https://prismlauncher.org/wiki/development/build-instructions/). From b989c5a36cdc4f8b1555c5bacb7e28e897f19cf0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 10 Jul 2024 16:24:31 +0300 Subject: [PATCH 08/26] refactor MinecraftUpdate Task Signed-off-by: Trial97 --- launcher/minecraft/MinecraftUpdate.cpp | 125 ++----------------------- launcher/minecraft/MinecraftUpdate.h | 32 +------ 2 files changed, 13 insertions(+), 144 deletions(-) diff --git a/launcher/minecraft/MinecraftUpdate.cpp b/launcher/minecraft/MinecraftUpdate.cpp index c009317a6..b63430aa8 100644 --- a/launcher/minecraft/MinecraftUpdate.cpp +++ b/launcher/minecraft/MinecraftUpdate.cpp @@ -16,32 +16,22 @@ #include "MinecraftUpdate.h" #include "MinecraftInstance.h" -#include -#include -#include -#include - -#include -#include "BaseInstance.h" -#include "minecraft/Library.h" #include "minecraft/PackProfile.h" +#include "tasks/SequentialTask.h" #include "update/AssetUpdateTask.h" #include "update/FMLLibrariesTask.h" #include "update/FoldersTask.h" #include "update/LibrariesTask.h" -#include -#include - -MinecraftUpdate::MinecraftUpdate(MinecraftInstance* inst, QObject* parent) : Task(parent), m_inst(inst) {} +MinecraftUpdate::MinecraftUpdate(MinecraftInstance* inst, QObject* parent) : SequentialTask(parent), m_inst(inst) {} void MinecraftUpdate::executeTask() { - m_tasks.clear(); + m_queue.clear(); // create folders { - m_tasks.append(makeShared(m_inst)); + addTask(makeShared(m_inst)); } // add metadata update task if necessary @@ -50,121 +40,24 @@ void MinecraftUpdate::executeTask() components->reload(Net::Mode::Online); auto task = components->getCurrentTask(); if (task) { - m_tasks.append(task); + addTask(task); } } // libraries download { - m_tasks.append(makeShared(m_inst)); + addTask(makeShared(m_inst)); } // FML libraries download and copy into the instance { - m_tasks.append(makeShared(m_inst)); + addTask(makeShared(m_inst)); } // assets update { - m_tasks.append(makeShared(m_inst)); + addTask(makeShared(m_inst)); } - if (!m_preFailure.isEmpty()) { - emitFailed(m_preFailure); - return; - } - next(); -} - -void MinecraftUpdate::next() -{ - if (m_abort) { - emitFailed(tr("Aborted by user.")); - return; - } - if (m_failed_out_of_order) { - emitFailed(m_fail_reason); - return; - } - m_currentTask++; - if (m_currentTask > 0) { - auto task = m_tasks[m_currentTask - 1]; - disconnect(task.get(), &Task::succeeded, this, &MinecraftUpdate::subtaskSucceeded); - disconnect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed); - disconnect(task.get(), &Task::aborted, this, &Task::abort); - disconnect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); - disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress); - disconnect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); - disconnect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); - } - if (m_currentTask == m_tasks.size()) { - emitSucceeded(); - return; - } - auto task = m_tasks[m_currentTask]; - // if the task is already finished by the time we look at it, skip it - if (task->isFinished()) { - qCritical() << "MinecraftUpdate: Skipping finished subtask" << m_currentTask << ":" << task.get(); - next(); - } - connect(task.get(), &Task::succeeded, this, &MinecraftUpdate::subtaskSucceeded); - connect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed); - connect(task.get(), &Task::aborted, this, &Task::abort); - connect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); - connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress); - connect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); - connect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); - // if the task is already running, do not start it again - if (!task->isRunning()) { - task->start(); - } -} - -void MinecraftUpdate::subtaskSucceeded() -{ - if (isFinished()) { - qCritical() << "MinecraftUpdate: Subtask" << sender() << "succeeded, but work was already done!"; - return; - } - auto senderTask = QObject::sender(); - auto currentTask = m_tasks[m_currentTask].get(); - if (senderTask != currentTask) { - qDebug() << "MinecraftUpdate: Subtask" << sender() << "succeeded out of order."; - return; - } - next(); -} - -void MinecraftUpdate::subtaskFailed(QString error) -{ - if (isFinished()) { - qCritical() << "MinecraftUpdate: Subtask" << sender() << "failed, but work was already done!"; - return; - } - auto senderTask = QObject::sender(); - auto currentTask = m_tasks[m_currentTask].get(); - if (senderTask != currentTask) { - qDebug() << "MinecraftUpdate: Subtask" << sender() << "failed out of order."; - m_failed_out_of_order = true; - m_fail_reason = error; - return; - } - emitFailed(error); -} - -bool MinecraftUpdate::abort() -{ - if (!m_abort) { - m_abort = true; - auto task = m_tasks[m_currentTask]; - if (task->canAbort()) { - return task->abort(); - } - } - return true; -} - -bool MinecraftUpdate::canAbort() const -{ - return true; + SequentialTask::executeTask(); } diff --git a/launcher/minecraft/MinecraftUpdate.h b/launcher/minecraft/MinecraftUpdate.h index 591c6afcb..456a13518 100644 --- a/launcher/minecraft/MinecraftUpdate.h +++ b/launcher/minecraft/MinecraftUpdate.h @@ -15,43 +15,19 @@ #pragma once -#include -#include -#include +#include "tasks/SequentialTask.h" -#include -#include "minecraft/VersionFilterData.h" -#include "net/NetJob.h" -#include "tasks/Task.h" - -class MinecraftVersion; class MinecraftInstance; -// FIXME: This looks very similar to a SequentialTask. Maybe we can reduce code duplications? :^) - -class MinecraftUpdate : public Task { +// this needs to be a task because components->reload does stuff that may block +class MinecraftUpdate : public SequentialTask { Q_OBJECT public: explicit MinecraftUpdate(MinecraftInstance* inst, QObject* parent = 0); - virtual ~MinecraftUpdate() {}; + virtual ~MinecraftUpdate() = default; void executeTask() override; - bool canAbort() const override; - - private slots: - bool abort() override; - void subtaskSucceeded(); - void subtaskFailed(QString error); - - private: - void next(); private: MinecraftInstance* m_inst = nullptr; - QList m_tasks; - QString m_preFailure; - int m_currentTask = -1; - bool m_abort = false; - bool m_failed_out_of_order = false; - QString m_fail_reason; }; From d3ca8864c228cd1131703c2164f9ab6856136976 Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Fri, 12 Jul 2024 23:54:22 +0300 Subject: [PATCH 09/26] chore: update Qt to 6.7.2 Signed-off-by: Edgars Cirulis --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8212af233..aa6e8f64f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -79,7 +79,7 @@ jobs: qt_ver: 6 qt_host: windows qt_arch: "" - qt_version: "6.7.1" + qt_version: "6.7.2" qt_modules: "qt5compat qtimageformats qtnetworkauth" - os: windows-2022 @@ -90,7 +90,7 @@ jobs: qt_ver: 6 qt_host: windows qt_arch: "win64_msvc2019_arm64" - qt_version: "6.7.1" + qt_version: "6.7.2" qt_modules: "qt5compat qtimageformats qtnetworkauth" - os: macos-12 @@ -99,7 +99,7 @@ jobs: qt_ver: 6 qt_host: mac qt_arch: "" - qt_version: "6.7.1" + qt_version: "6.7.2" qt_modules: "qt5compat qtimageformats qtnetworkauth" - os: macos-12 From fc2d0134024619c84eda5649df2196e5600c3808 Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Sat, 20 Jul 2024 01:50:30 +0300 Subject: [PATCH 10/26] ui: swap timeoutSecondsLabel and numberOfManualRetriesLabel order fixes: 7a200a337f08cfa1e32102594958f10cb7f000c6 conflicted with 6078a771c18fd749f38d7c1a2f80ed3c7ec7ad28 Signed-off-by: Edgars Cirulis --- launcher/ui/pages/global/LauncherPage.ui | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index b3387ba02..72039488b 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -291,6 +291,20 @@ + + + Number of manual retries + + + + + + + 0 + + + + Seconds to wait until the requests are terminated @@ -300,27 +314,13 @@ - + s - - - - Number of manual retries - - - - - - - 0 - - - From ff31e88cf8a1280c0ab93033a51832037b938883 Mon Sep 17 00:00:00 2001 From: Evan Goode Date: Sat, 20 Jul 2024 18:40:32 -0400 Subject: [PATCH 11/26] nix: sync changes from nixpkgs Brings in changes from the Prism Launcher derivation(s) in nixpkgs, notably from https://github.com/NixOS/nixpkgs/pull/321851 and https://github.com/NixOS/nixpkgs/pull/303880 Signed-off-by: Evan Goode --- nix/distribution.nix | 3 +- nix/pkg/default.nix | 107 +++++++++++++++++++------------- nix/pkg/wrapper.nix | 143 +++++++++++++++++++++++++++++-------------- 3 files changed, 160 insertions(+), 93 deletions(-) diff --git a/nix/distribution.nix b/nix/distribution.nix index d9c6784a1..28ef7ced1 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -24,9 +24,8 @@ overlays.default = final: prev: let version = builtins.substring 0 8 self.lastModifiedDate or "dirty"; in { - prismlauncher-unwrapped = prev.qt6Packages.callPackage ./pkg { + prismlauncher-unwrapped = prev.callPackage ./pkg { inherit (inputs) libnbtplusplus; - inherit ((final.darwin or prev.darwin).apple_sdk.frameworks) Cocoa; inherit version; }; diff --git a/nix/pkg/default.nix b/nix/pkg/default.nix index 1a3d8224f..f3ff3789c 100644 --- a/nix/pkg/default.nix +++ b/nix/pkg/default.nix @@ -1,27 +1,27 @@ { lib, stdenv, - canonicalize-jars-hook, cmake, cmark, - Cocoa, - ninja, - jdk17, - zlib, - qtbase, - qtnetworkauth, - quazip, + darwin, extra-cmake-modules, - tomlplusplus, - ghc_filesystem, gamemode, + ghc_filesystem, + jdk17, + kdePackages, + ninja, + stripJavaArchivesHook, + tomlplusplus, + zlib, msaClientID ? null, gamemodeSupport ? stdenv.isLinux, version, libnbtplusplus, }: -assert lib.assertMsg (stdenv.isLinux || !gamemodeSupport) "gamemodeSupport is only available on Linux"; - stdenv.mkDerivation rec { +assert lib.assertMsg ( + gamemodeSupport -> stdenv.isLinux +) "gamemodeSupport is only available on Linux."; + stdenv.mkDerivation { pname = "prismlauncher-unwrapped"; inherit version; @@ -39,49 +39,68 @@ assert lib.assertMsg (stdenv.isLinux || !gamemodeSupport) "gamemodeSupport is on ]); }; - nativeBuildInputs = [extra-cmake-modules cmake jdk17 ninja canonicalize-jars-hook]; - buildInputs = - [ - qtbase - qtnetworkauth - zlib - quazip - ghc_filesystem - tomlplusplus - cmark - ] - ++ lib.optional gamemodeSupport gamemode - ++ lib.optionals stdenv.isDarwin [Cocoa]; - - hardeningEnable = lib.optionals stdenv.isLinux ["pie"]; - - cmakeFlags = - [ - "-DLauncher_BUILD_PLATFORM=nixpkgs" - ] - ++ lib.optionals (msaClientID != null) ["-DLauncher_MSA_CLIENT_ID=${msaClientID}"] - ++ lib.optionals (lib.versionOlder qtbase.version "6") ["-DLauncher_QT_VERSION_MAJOR=5"] - ++ lib.optionals stdenv.isDarwin ["-DINSTALL_BUNDLE=nodeps" "-DMACOSX_SPARKLE_UPDATE_FEED_URL=''"]; - postUnpack = '' rm -rf source/libraries/libnbtplusplus ln -s ${libnbtplusplus} source/libraries/libnbtplusplus ''; + nativeBuildInputs = [ + cmake + ninja + extra-cmake-modules + jdk17 + stripJavaArchivesHook + ]; + + buildInputs = + [ + cmark + ghc_filesystem + kdePackages.qtbase + kdePackages.qtnetworkauth + kdePackages.quazip + tomlplusplus + zlib + ] + ++ lib.optionals stdenv.isDarwin [darwin.apple_sdk.frameworks.Cocoa] + ++ lib.optional gamemodeSupport gamemode; + + hardeningEnable = lib.optionals stdenv.isLinux ["pie"]; + + cmakeFlags = + [ + (lib.cmakeFeature "Launcher_BUILD_PLATFORM" "nixpkgs") + ] + ++ lib.optionals (msaClientID != null) [ + (lib.cmakeFeature "Launcher_MSA_CLIENT_ID" (toString msaClientID)) + ] + ++ lib.optionals (lib.versionOlder kdePackages.qtbase.version "6") [ + (lib.cmakeFeature "Launcher_QT_VERSION_MAJOR" "5") + ] + ++ lib.optionals stdenv.isDarwin [ + # we wrap our binary manually + (lib.cmakeFeature "INSTALL_BUNDLE" "nodeps") + # disable built-in updater + (lib.cmakeFeature "MACOSX_SPARKLE_UPDATE_FEED_URL" "''") + (lib.cmakeFeature "CMAKE_INSTALL_PREFIX" "${placeholder "out"}/Applications/") + ]; + dontWrapQtApps = true; - meta = with lib; { - mainProgram = "prismlauncher"; - homepage = "https://prismlauncher.org/"; - description = "A free, open source launcher for Minecraft"; + meta = { + description = "Free, open source launcher for Minecraft"; longDescription = '' Allows you to have multiple, separate instances of Minecraft (each with their own mods, texture packs, saves, etc) and helps you manage them and their associated options with a simple interface. ''; - platforms = with platforms; linux ++ darwin; - changelog = "https://github.com/PrismLauncher/PrismLauncher/releases/tag/${version}"; - license = licenses.gpl3Only; - maintainers = with maintainers; [minion3665 Scrumplex getchoo]; + homepage = "https://prismlauncher.org/"; + license = lib.licenses.gpl3Only; + maintainers = with lib.maintainers; [ + Scrumplex + getchoo + ]; + mainProgram = "prismlauncher"; + platforms = lib.platforms.linux ++ lib.platforms.darwin; }; } diff --git a/nix/pkg/wrapper.nix b/nix/pkg/wrapper.nix index 8c9c1cabc..e7516397e 100644 --- a/nix/pkg/wrapper.nix +++ b/nix/pkg/wrapper.nix @@ -3,94 +3,143 @@ stdenv, symlinkJoin, prismlauncher-unwrapped, - wrapQtAppsHook, addOpenGLRunpath, - qtbase, # needed for wrapQtAppsHook - qtsvg, - qtwayland, - xorg, - libpulseaudio, - libGL, + flite, + gamemode, glfw, - openal, + glfw-wayland-minecraft, + glxinfo, jdk8, jdk17, jdk21, - gamemode, - flite, - glxinfo, - udev, + kdePackages, + libGL, + libpulseaudio, libusb1, - msaClientID ? null, - gamemodeSupport ? stdenv.isLinux, - textToSpeechSupport ? stdenv.isLinux, - controllerSupport ? stdenv.isLinux, - jdks ? [jdk21 jdk17 jdk8], + makeWrapper, + openal, + pciutils, + udev, + vulkan-loader, + xorg, additionalLibs ? [], additionalPrograms ? [], -}: let - prismlauncherFinal = prismlauncher-unwrapped.override { - inherit msaClientID gamemodeSupport; - }; + controllerSupport ? stdenv.isLinux, + gamemodeSupport ? stdenv.isLinux, + jdks ? [ + jdk21 + jdk17 + jdk8 + ], + msaClientID ? null, + textToSpeechSupport ? stdenv.isLinux, + # Adds `glfw-wayland-minecraft` to `LD_LIBRARY_PATH` + # when launched on wayland, allowing for the game to be run natively. + # Make sure to enable "Use system installation of GLFW" in instance settings + # for this to take effect + # + # Warning: This build of glfw may be unstable, and the launcher + # itself can take slightly longer to start + withWaylandGLFW ? false, +}: +assert lib.assertMsg ( + controllerSupport -> stdenv.isLinux +) "controllerSupport only has an effect on Linux."; +assert lib.assertMsg ( + textToSpeechSupport -> stdenv.isLinux +) "textToSpeechSupport only has an effect on Linux."; +assert lib.assertMsg ( + withWaylandGLFW -> stdenv.isLinux +) "withWaylandGLFW is only available on Linux."; let + prismlauncher' = prismlauncher-unwrapped.override {inherit msaClientID gamemodeSupport;}; in symlinkJoin { - name = "prismlauncher-${prismlauncherFinal.version}"; + name = "prismlauncher-${prismlauncher'.version}"; - paths = [prismlauncherFinal]; + paths = [prismlauncher']; - nativeBuildInputs = [ - wrapQtAppsHook - ]; + nativeBuildInputs = + [kdePackages.wrapQtAppsHook] + # purposefully using a shell wrapper here for variable expansion + # see https://github.com/NixOS/nixpkgs/issues/172583 + ++ lib.optional withWaylandGLFW makeWrapper; buildInputs = [ - qtbase - qtsvg + kdePackages.qtbase + kdePackages.qtsvg ] - ++ lib.optional (lib.versionAtLeast qtbase.version "6" && stdenv.isLinux) qtwayland; + ++ lib.optional ( + lib.versionAtLeast kdePackages.qtbase.version "6" && stdenv.isLinux + ) + kdePackages.qtwayland; - postBuild = '' - wrapQtAppsHook - ''; + env = { + waylandPreExec = lib.optionalString withWaylandGLFW '' + if [ -n "$WAYLAND_DISPLAY" ]; then + export LD_LIBRARY_PATH=${lib.getLib glfw-wayland-minecraft}/lib:"$LD_LIBRARY_PATH" + fi + ''; + }; + + postBuild = + lib.optionalString withWaylandGLFW '' + qtWrapperArgs+=(--run "$waylandPreExec") + '' + + '' + wrapQtAppsHook + ''; qtWrapperArgs = let runtimeLibs = - (with xorg; [ - libX11 - libXext - libXcursor - libXrandr - libXxf86vm - ]) - ++ [ + [ # lwjgl + glfw libpulseaudio libGL - glfw openal stdenv.cc.cc.lib - # oshi - udev + vulkan-loader # VulkanMod's lwjgl + + udev # oshi + + xorg.libX11 + xorg.libXext + xorg.libXcursor + xorg.libXrandr + xorg.libXxf86vm ] - ++ lib.optional gamemodeSupport gamemode.lib ++ lib.optional textToSpeechSupport flite + ++ lib.optional gamemodeSupport gamemode.lib ++ lib.optional controllerSupport libusb1 ++ additionalLibs; runtimePrograms = [ - xorg.xrandr glxinfo + pciutils # need lspci + xorg.xrandr # needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128 ] ++ additionalPrograms; in ["--prefix PRISMLAUNCHER_JAVA_PATHS : ${lib.makeSearchPath "bin/java" jdks}"] ++ lib.optionals stdenv.isLinux [ "--set LD_LIBRARY_PATH ${addOpenGLRunpath.driverLink}/lib:${lib.makeLibraryPath runtimeLibs}" - # xorg.xrandr needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128 "--prefix PATH : ${lib.makeBinPath runtimePrograms}" ]; - inherit (prismlauncherFinal) meta; + meta = { + inherit + (prismlauncher'.meta) + description + longDescription + homepage + changelog + license + maintainers + mainProgram + platforms + ; + }; } From 33bf370d17a90f6bfaa4859a05db4230e5dadd92 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Mon, 22 Jul 2024 21:51:20 +0300 Subject: [PATCH 12/26] Update launcher/net/RawHeaderProxy.h Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/net/RawHeaderProxy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/net/RawHeaderProxy.h b/launcher/net/RawHeaderProxy.h index 682cc9e4d..9de18efc7 100644 --- a/launcher/net/RawHeaderProxy.h +++ b/launcher/net/RawHeaderProxy.h @@ -28,7 +28,7 @@ namespace Net { class RawHeaderProxy : public HeaderProxy { public: - RawHeaderProxy(QList headers = {}) : HeaderProxy(), m_headers(headers) {}; + RawHeaderProxy(QList headers = {}) : HeaderProxy(), m_headers(std::move(headers)) {}; virtual ~RawHeaderProxy() = default; public: From 61e62dce1bd7727b85679b7e3b76af9a382e1f59 Mon Sep 17 00:00:00 2001 From: src_resources Date: Mon, 29 Jul 2024 21:04:23 +0800 Subject: [PATCH 13/26] Fix a typo in comment Signed-off-by: src_resources --- launcher/FileSystem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index 66adf7a36..c5beef7bd 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -72,7 +72,7 @@ void appendSafe(const QString& filename, const QByteArray& data); void append(const QString& filename, const QByteArray& data); /** - * read data from a file safely\ + * read data from a file safely */ QByteArray read(const QString& filename); From ca5df3ea609be9962a58af85471006da4b355bb0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 30 Jul 2024 01:32:46 +0300 Subject: [PATCH 14/26] ensure minimal folder permissions when extracting files Signed-off-by: Trial97 --- launcher/MMCZip.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 00658b42b..cb9ee9940 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -344,6 +344,17 @@ std::optional extractSubDir(QuaZip* zip, const QString& subdir, con qWarning() << (QObject::tr("Could not fix permissions for %1").arg(target_file_path)); } } + } else if (fileInfo.isDir()) { + // Ensure the folder has the minimal required permissions + QFile::Permissions minimalPermissions = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | QFile::ReadGroup | + QFile::ExeGroup | QFile::ReadOther | QFile::ExeOther; + + QFile::Permissions currentPermissions = fileInfo.permissions(); + if ((currentPermissions & minimalPermissions) != minimalPermissions) { + if (!QFile::setPermissions(target_file_path, minimalPermissions)) { + qWarning() << (QObject::tr("Could not fix permissions for %1").arg(target_file_path)); + } + } } qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path; } while (zip->goToNextFile()); @@ -560,7 +571,7 @@ auto ExtractZipTask::extractZip() -> ZipResult if (!file_name.startsWith(m_subdirectory)) continue; - auto relative_file_name = QDir::fromNativeSeparators(file_name.remove(0, m_subdirectory.size())); + auto relative_file_name = QDir::fromNativeSeparators(file_name.mid(m_subdirectory.size())); auto original_name = relative_file_name; setStatus("Unziping: " + relative_file_name); @@ -610,6 +621,17 @@ auto ExtractZipTask::extractZip() -> ZipResult logWarning(tr("Could not fix permissions for %1").arg(target_file_path)); } } + } else if (fileInfo.isDir()) { + // Ensure the folder has the minimal required permissions + QFile::Permissions minimalPermissions = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | QFile::ReadGroup | + QFile::ExeGroup | QFile::ReadOther | QFile::ExeOther; + + QFile::Permissions currentPermissions = fileInfo.permissions(); + if ((currentPermissions & minimalPermissions) != minimalPermissions) { + if (!QFile::setPermissions(target_file_path, minimalPermissions)) { + logWarning(tr("Could not fix permissions for %1").arg(target_file_path)); + } + } } qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path; From ba7391308e2b4e22c87d66468a1c837fa34b444b Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Mon, 5 Aug 2024 22:05:23 +0300 Subject: [PATCH 15/26] Restore connect line for device authorization in MSADeviceCodeStep Parent PRs: https://github.com/PrismLauncher/PrismLauncher/pull/2617 Fixes https://github.com/PrismLauncher/PrismLauncher/issues/2705 Signed-off-by: Edgars Cirulis --- launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp index 9626dfeb4..c283b153e 100644 --- a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp +++ b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp @@ -74,6 +74,8 @@ void MSADeviceCodeStep::perform() m_task->setAskRetry(false); m_task->addNetAction(m_request); + connect(m_task.get(), &Task::finished, this, &MSADeviceCodeStep::deviceAutorizationFinished); + m_task->start(); } From 128827cef50d7ab4e332e8e26bc21db425237de3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 20:02:40 +0000 Subject: [PATCH 16/26] chore(deps): update hendrikmuhs/ccache-action action to v1.2.14 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aa6e8f64f..a521a6e45 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -160,7 +160,7 @@ jobs: - name: Setup ccache if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug' - uses: hendrikmuhs/ccache-action@v1.2.13 + uses: hendrikmuhs/ccache-action@v1.2.14 with: key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }} From 659fa7fbfb3a5e761efbaeb207a9014b7affafde Mon Sep 17 00:00:00 2001 From: Kationor Date: Wed, 7 Aug 2024 16:21:34 +0200 Subject: [PATCH 17/26] fix/windows: Check registry for per-user java installations Signed-off-by: Kationor --- launcher/java/JavaUtils.cpp | 78 +++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 34d893ff2..350ccc30d 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -182,56 +182,58 @@ QList JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString else if (keyType == KEY_WOW64_32KEY) archType = "32"; - HKEY jreKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName.toStdWString().c_str(), 0, KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == - ERROR_SUCCESS) { - // Read the current type version from the registry. - // This will be used to find any key that contains the JavaHome value. + for (HKEY baseRegistry : { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }) { + HKEY jreKey; + if (RegOpenKeyExW(baseRegistry, keyName.toStdWString().c_str(), 0, KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == + ERROR_SUCCESS) { + // Read the current type version from the registry. + // This will be used to find any key that contains the JavaHome value. - WCHAR subKeyName[255]; - DWORD subKeyNameSize, numSubKeys, retCode; + WCHAR subKeyName[255]; + DWORD subKeyNameSize, numSubKeys, retCode; - // Get the number of subkeys - RegQueryInfoKeyW(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + // Get the number of subkeys + RegQueryInfoKeyW(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - // Iterate until RegEnumKeyEx fails - if (numSubKeys > 0) { - for (DWORD i = 0; i < numSubKeys; i++) { - subKeyNameSize = 255; - retCode = RegEnumKeyExW(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL); - QString newSubkeyName = QString::fromWCharArray(subKeyName); - if (retCode == ERROR_SUCCESS) { - // Now open the registry key for the version that we just got. - QString newKeyName = keyName + "\\" + newSubkeyName + subkeySuffix; + // Iterate until RegEnumKeyEx fails + if (numSubKeys > 0) { + for (DWORD i = 0; i < numSubKeys; i++) { + subKeyNameSize = 255; + retCode = RegEnumKeyExW(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL); + QString newSubkeyName = QString::fromWCharArray(subKeyName); + if (retCode == ERROR_SUCCESS) { + // Now open the registry key for the version that we just got. + QString newKeyName = keyName + "\\" + newSubkeyName + subkeySuffix; - HKEY newKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, newKeyName.toStdWString().c_str(), 0, KEY_READ | keyType, &newKey) == - ERROR_SUCCESS) { - // Read the JavaHome value to find where Java is installed. - DWORD valueSz = 0; - if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, NULL, &valueSz) == ERROR_SUCCESS) { - WCHAR* value = new WCHAR[valueSz]; - RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE*)value, &valueSz); + HKEY newKey; + if (RegOpenKeyExW(baseRegistry, newKeyName.toStdWString().c_str(), 0, KEY_READ | keyType, &newKey) == + ERROR_SUCCESS) { + // Read the JavaHome value to find where Java is installed. + DWORD valueSz = 0; + if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, NULL, &valueSz) == ERROR_SUCCESS) { + WCHAR* value = new WCHAR[valueSz]; + RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE*)value, &valueSz); - QString newValue = QString::fromWCharArray(value); - delete[] value; + QString newValue = QString::fromWCharArray(value); + delete[] value; - // Now, we construct the version object and add it to the list. - JavaInstallPtr javaVersion(new JavaInstall()); + // Now, we construct the version object and add it to the list. + JavaInstallPtr javaVersion(new JavaInstall()); - javaVersion->id = newSubkeyName; - javaVersion->arch = archType; - javaVersion->path = QDir(FS::PathCombine(newValue, "bin")).absoluteFilePath("javaw.exe"); - javas.append(javaVersion); + javaVersion->id = newSubkeyName; + javaVersion->arch = archType; + javaVersion->path = QDir(FS::PathCombine(newValue, "bin")).absoluteFilePath("javaw.exe"); + javas.append(javaVersion); + } + + RegCloseKey(newKey); } - - RegCloseKey(newKey); } } } - } - RegCloseKey(jreKey); + RegCloseKey(jreKey); + } } return javas; From c9809fff6d88643e723b492dde835bd806a9c076 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Aug 2024 16:53:26 +0300 Subject: [PATCH 18/26] add setting for quickplay singleplayer Signed-off-by: Trial97 --- launcher/Application.cpp | 47 +++++++------ launcher/Application.h | 7 +- launcher/BaseInstance.h | 6 +- launcher/CMakeLists.txt | 4 +- launcher/InstancePageProvider.h | 4 +- launcher/LaunchController.cpp | 2 +- launcher/LaunchController.h | 8 +-- launcher/NullInstance.h | 6 +- launcher/launch/steps/LookupServerAddress.cpp | 2 +- launcher/launch/steps/LookupServerAddress.h | 8 +-- launcher/minecraft/MinecraftInstance.cpp | 69 +++++++++++-------- launcher/minecraft/MinecraftInstance.h | 12 ++-- .../minecraft/launch/LauncherPartLaunch.cpp | 2 +- .../minecraft/launch/LauncherPartLaunch.h | 8 +-- ...ftServerTarget.cpp => MinecraftTarget.cpp} | 11 ++- ...ecraftServerTarget.h => MinecraftTarget.h} | 8 +-- .../minecraft/launch/PrintInstanceInfo.cpp | 2 +- launcher/minecraft/launch/PrintInstanceInfo.h | 11 ++- .../pages/instance/InstanceSettingsPage.cpp | 57 ++++++++++++++- .../ui/pages/instance/InstanceSettingsPage.h | 3 + .../ui/pages/instance/InstanceSettingsPage.ui | 42 +++++------ launcher/ui/pages/instance/ServersPage.cpp | 4 +- launcher/ui/pages/instance/WorldListPage.cpp | 18 ++++- launcher/ui/pages/instance/WorldListPage.h | 5 +- launcher/ui/pages/instance/WorldListPage.ui | 6 ++ launcher/ui/widgets/WideBar.cpp | 13 ++++ launcher/ui/widgets/WideBar.h | 2 + .../launcher/impl/AbstractLauncher.java | 3 +- .../launcher/impl/StandardLauncher.java | 11 ++- 29 files changed, 253 insertions(+), 128 deletions(-) rename launcher/minecraft/launch/{MinecraftServerTarget.cpp => MinecraftTarget.cpp} (86%) rename launcher/minecraft/launch/{MinecraftServerTarget.h => MinecraftTarget.h} (80%) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 6c0319984..84b759e09 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -236,6 +236,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) { { { "d", "dir" }, "Use a custom path as application root (use '.' for current directory)", "directory" }, { { "l", "launch" }, "Launch the specified instance (by instance ID)", "instance" }, { { "s", "server" }, "Join the specified server on launch (only valid in combination with --launch)", "address" }, + { { "w", "world" }, "Join the specified world on launch (only valid in combination with --launch)", "world" }, { { "a", "profile" }, "Use the account specified by its profile name (only valid in combination with --launch)", "profile" }, { "alive", "Write a small '" + liveCheckFile + "' file after the launcher starts" }, { { "I", "import" }, "Import instance or resource from specified local path or URL", "url" }, @@ -249,7 +250,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) parser.process(arguments()); m_instanceIdToLaunch = parser.value("launch"); - m_serverToJoin = parser.value("server"); + m_server_to_join = parser.value("server"); + m_world_to_join = parser.value("world"); m_profileToUse = parser.value("profile"); m_liveCheck = parser.isSet("alive"); @@ -265,7 +267,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) } // error if --launch is missing with --server or --profile - if ((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { + if (((!m_server_to_join.isEmpty() || !m_world_to_join.isEmpty()) || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl; m_status = Application::Failed; return; @@ -383,8 +385,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) launch.command = "launch"; launch.args["id"] = m_instanceIdToLaunch; - if (!m_serverToJoin.isEmpty()) { - launch.args["server"] = m_serverToJoin; + if (!m_server_to_join.isEmpty()) { + launch.args["server"] = m_server_to_join; + } else if (!m_world_to_join.isEmpty()) { + launch.args["world"] = m_world_to_join; } if (!m_profileToUse.isEmpty()) { launch.args["profile"] = m_profileToUse; @@ -521,8 +525,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) if (!m_instanceIdToLaunch.isEmpty()) { qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch; } - if (!m_serverToJoin.isEmpty()) { - qDebug() << "Address of server to join :" << m_serverToJoin; + if (!m_server_to_join.isEmpty()) { + qDebug() << "Address of server to join :" << m_server_to_join; + } else if (!m_world_to_join.isEmpty()) { + qDebug() << "Name of the world to join :" << m_world_to_join; } qDebug() << "<> Paths set."; } @@ -1157,14 +1163,17 @@ void Application::performMainStartupAction() if (!m_instanceIdToLaunch.isEmpty()) { auto inst = instances()->getInstanceById(m_instanceIdToLaunch); if (inst) { - MinecraftServerTargetPtr serverToJoin = nullptr; + MinecraftTarget::Ptr targetToJoin = nullptr; MinecraftAccountPtr accountToUse = nullptr; qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching"; - if (!m_serverToJoin.isEmpty()) { + if (!m_server_to_join.isEmpty()) { // FIXME: validate the server string - serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(m_serverToJoin))); - qDebug() << " Launching with server" << m_serverToJoin; + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_server_to_join, false))); + qDebug() << " Launching with server" << m_server_to_join; + } else if (!m_world_to_join.isEmpty()) { + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_world_to_join, true))); + qDebug() << " Launching with world" << m_world_to_join; } if (!m_profileToUse.isEmpty()) { @@ -1175,7 +1184,7 @@ void Application::performMainStartupAction() qDebug() << " Launching with account" << m_profileToUse; } - launch(inst, true, false, serverToJoin, accountToUse); + launch(inst, true, false, targetToJoin, accountToUse); return; } } @@ -1265,6 +1274,7 @@ void Application::messageReceived(const QByteArray& message) } else if (command == "launch") { QString id = received.args["id"]; QString server = received.args["server"]; + QString world = received.args["world"]; QString profile = received.args["profile"]; InstancePtr instance; @@ -1279,11 +1289,12 @@ void Application::messageReceived(const QByteArray& message) return; } - MinecraftServerTargetPtr serverObject = nullptr; + MinecraftTarget::Ptr serverObject = nullptr; if (!server.isEmpty()) { - serverObject = std::make_shared(MinecraftServerTarget::parse(server)); + serverObject = std::make_shared(MinecraftTarget::parse(server, false)); + } else if (!world.isEmpty()) { + serverObject = std::make_shared(MinecraftTarget::parse(world, true)); } - MinecraftAccountPtr accountObject; if (!profile.isEmpty()) { accountObject = accounts()->getAccountByProfileName(profile); @@ -1332,11 +1343,7 @@ bool Application::openJsonEditor(const QString& filename) } } -bool Application::launch(InstancePtr instance, - bool online, - bool demo, - MinecraftServerTargetPtr serverToJoin, - MinecraftAccountPtr accountToUse) +bool Application::launch(InstancePtr instance, bool online, bool demo, MinecraftTarget::Ptr targetToJoin, MinecraftAccountPtr accountToUse) { if (m_updateRunning) { qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed."; @@ -1354,7 +1361,7 @@ bool Application::launch(InstancePtr instance, controller->setOnline(online); controller->setDemo(demo); controller->setProfiler(profilers().value(instance->settings()->get("Profiler").toString(), nullptr).get()); - controller->setServerToJoin(serverToJoin); + controller->setTargetToJoin(targetToJoin); controller->setAccountToUse(accountToUse); if (window) { controller->setParentWidget(window); diff --git a/launcher/Application.h b/launcher/Application.h index 8303c7475..fb54b1005 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -47,7 +47,7 @@ #include -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" class LaunchController; class LocalPeer; @@ -202,7 +202,7 @@ class Application : public QApplication { bool launch(InstancePtr instance, bool online = true, bool demo = false, - MinecraftServerTargetPtr serverToJoin = nullptr, + MinecraftTarget::Ptr targetToJoin = nullptr, MinecraftAccountPtr accountToUse = nullptr); bool kill(InstancePtr instance); void closeCurrentWindow(); @@ -289,7 +289,8 @@ class Application : public QApplication { QString m_detectedGLFWPath; QString m_detectedOpenALPath; QString m_instanceIdToLaunch; - QString m_serverToJoin; + QString m_server_to_join; + QString m_world_to_join; QString m_profileToUse; bool m_liveCheck = false; QList m_urlsToImport; diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h index 499ec7866..8c80331bc 100644 --- a/launcher/BaseInstance.h +++ b/launcher/BaseInstance.h @@ -56,7 +56,7 @@ #include "net/Mode.h" #include "RuntimeContext.h" -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" class QDir; class Task; @@ -184,7 +184,7 @@ class BaseInstance : public QObject, public std::enable_shared_from_this createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0; + virtual shared_qobject_ptr createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) = 0; /// returns the current launch task (if any) shared_qobject_ptr getLaunchTask(); @@ -256,7 +256,7 @@ class BaseInstance : public QObject, public std::enable_shared_from_this getPages() override { QList values; @@ -39,7 +39,7 @@ class InstancePageProvider : protected QObject, public BasePageProvider { values.append(new TexturePackPage(onesix.get(), onesix->texturePackList())); values.append(new ShaderPackPage(onesix.get(), onesix->shaderPackList())); values.append(new NotesPage(onesix.get())); - values.append(new WorldListPage(onesix.get(), onesix->worldList())); + values.append(new WorldListPage(onesix, onesix->worldList())); values.append(new ServersPage(onesix)); // values.append(new GameOptionsPage(onesix.get())); values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 3866a7672..83bf3838e 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -324,7 +324,7 @@ void LaunchController::launchInstance() return; } - m_launcher = m_instance->createLaunchTask(m_session, m_serverToJoin); + m_launcher = m_instance->createLaunchTask(m_session, m_target_to_join); if (!m_launcher) { emitFailed(tr("Couldn't instantiate a launcher.")); return; diff --git a/launcher/LaunchController.h b/launcher/LaunchController.h index bc688f2ba..e620b8c62 100644 --- a/launcher/LaunchController.h +++ b/launcher/LaunchController.h @@ -39,7 +39,7 @@ #include #include "minecraft/auth/MinecraftAccount.h" -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" class InstanceWindow; class LaunchController : public Task { @@ -48,7 +48,7 @@ class LaunchController : public Task { void executeTask() override; LaunchController(QObject* parent = nullptr); - virtual ~LaunchController() {}; + virtual ~LaunchController() = default; void setInstance(InstancePtr instance) { m_instance = instance; } @@ -62,7 +62,7 @@ class LaunchController : public Task { void setParentWidget(QWidget* widget) { m_parentWidget = widget; } - void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { m_serverToJoin = std::move(serverToJoin); } + void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_target_to_join = std::move(targetToJoin); } void setAccountToUse(MinecraftAccountPtr accountToUse) { m_accountToUse = std::move(accountToUse); } @@ -94,5 +94,5 @@ class LaunchController : public Task { MinecraftAccountPtr m_accountToUse = nullptr; AuthSessionPtr m_session; shared_qobject_ptr m_launcher; - MinecraftServerTargetPtr m_serverToJoin; + MinecraftTarget::Ptr m_target_to_join; }; diff --git a/launcher/NullInstance.h b/launcher/NullInstance.h index b6a9478a8..3ee38e76c 100644 --- a/launcher/NullInstance.h +++ b/launcher/NullInstance.h @@ -46,13 +46,13 @@ class NullInstance : public BaseInstance { { setVersionBroken(true); } - virtual ~NullInstance() {}; + virtual ~NullInstance() = default; void saveNow() override {} void loadSpecificSettings() override { setSpecificSettingsLoaded(true); } QString getStatusbarDescription() override { return tr("Unknown instance type"); }; QSet traits() const override { return {}; }; QString instanceConfigFolder() const override { return instanceRoot(); }; - shared_qobject_ptr createLaunchTask(AuthSessionPtr, MinecraftServerTargetPtr) override { return nullptr; } + shared_qobject_ptr createLaunchTask(AuthSessionPtr, MinecraftTarget::Ptr) override { return nullptr; } shared_qobject_ptr createUpdateTask([[maybe_unused]] Net::Mode mode) override { return nullptr; } QProcessEnvironment createEnvironment() override { return QProcessEnvironment(); } QProcessEnvironment createLaunchEnvironment() override { return QProcessEnvironment(); } @@ -64,7 +64,7 @@ class NullInstance : public BaseInstance { bool canEdit() const override { return false; } bool canLaunch() const override { return false; } void populateLaunchMenu(QMenu* menu) override {} - QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override + QStringList verboseDescription(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) override { QStringList out; out << "Null instance - placeholder."; diff --git a/launcher/launch/steps/LookupServerAddress.cpp b/launcher/launch/steps/LookupServerAddress.cpp index 9bdac203b..4b67b3092 100644 --- a/launcher/launch/steps/LookupServerAddress.cpp +++ b/launcher/launch/steps/LookupServerAddress.cpp @@ -30,7 +30,7 @@ void LookupServerAddress::setLookupAddress(const QString& lookupAddress) m_dnsLookup->setName(QString("_minecraft._tcp.%1").arg(lookupAddress)); } -void LookupServerAddress::setOutputAddressPtr(MinecraftServerTargetPtr output) +void LookupServerAddress::setOutputAddressPtr(MinecraftTarget::Ptr output) { m_output = std::move(output); } diff --git a/launcher/launch/steps/LookupServerAddress.h b/launcher/launch/steps/LookupServerAddress.h index acbd74309..506314ee8 100644 --- a/launcher/launch/steps/LookupServerAddress.h +++ b/launcher/launch/steps/LookupServerAddress.h @@ -19,20 +19,20 @@ #include #include -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" class LookupServerAddress : public LaunchStep { Q_OBJECT public: explicit LookupServerAddress(LaunchTask* parent); - virtual ~LookupServerAddress() {}; + virtual ~LookupServerAddress() = default; virtual void executeTask(); virtual bool abort(); virtual bool canAbort() const { return true; } void setLookupAddress(const QString& lookupAddress); - void setOutputAddressPtr(MinecraftServerTargetPtr output); + void setOutputAddressPtr(MinecraftTarget::Ptr output); private slots: void on_dnsLookupFinished(); @@ -42,5 +42,5 @@ class LookupServerAddress : public LaunchStep { QDnsLookup* m_dnsLookup; QString m_lookupAddress; - MinecraftServerTargetPtr m_output; + MinecraftTarget::Ptr m_output; }; diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index d119104fe..c50d57513 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -196,8 +196,9 @@ void MinecraftInstance::loadSpecificSettings() } // Join server on launch, this does not have a global override - m_settings->registerSetting("JoinServerOnLaunch", false); + m_settings->registerSetting({ "JoinServerOnLaunch", "JoinOnLaunch" }, false); m_settings->registerSetting("JoinServerOnLaunchAddress", ""); + m_settings->registerSetting("JoinWorldOnLaunch", ""); // Use account for instance, this does not have a global override m_settings->registerSetting("UseAccountForInstance", false); @@ -523,8 +524,7 @@ QStringList MinecraftInstance::javaArguments() if (javaVersion.isModular() && shouldApplyOnlineFixes()) // allow reflective access to java.net - required by the skin fix - args << "--add-opens" - << "java.base/java.net=ALL-UNNAMED"; + args << "--add-opens" << "java.base/java.net=ALL-UNNAMED"; return args; } @@ -656,7 +656,7 @@ static QString replaceTokensIn(QString text, QMap with) return result; } -QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) const +QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) const { auto profile = m_components->getProfile(); QString args_pattern = profile->getMinecraftArguments(); @@ -664,12 +664,16 @@ QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, Mine args_pattern += " --tweakClass " + tweaker; } - if (serverToJoin && !serverToJoin->address.isEmpty()) { - if (profile->hasTrait("feature:is_quick_play_multiplayer")) { - args_pattern += " --quickPlayMultiplayer " + serverToJoin->address + ':' + QString::number(serverToJoin->port); - } else { - args_pattern += " --server " + serverToJoin->address; - args_pattern += " --port " + QString::number(serverToJoin->port); + if (targetToJoin) { + if (!targetToJoin->address.isEmpty()) { + if (profile->hasTrait("feature:is_quick_play_multiplayer")) { + args_pattern += " --quickPlayMultiplayer " + targetToJoin->address + ':' + QString::number(targetToJoin->port); + } else { + args_pattern += " --server " + targetToJoin->address; + args_pattern += " --port " + QString::number(targetToJoin->port); + } + } else if (!targetToJoin->world.isEmpty() && profile->hasTrait("feature:is_quick_play_singleplayer")) { + args_pattern += " --quickPlaySingleplayer " + targetToJoin->world; } } @@ -713,7 +717,7 @@ QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, Mine return parts; } -QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) +QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) { QString launchScript; @@ -732,9 +736,13 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS launchScript += "appletClass " + appletClass + "\n"; } - if (serverToJoin && !serverToJoin->address.isEmpty()) { - launchScript += "serverAddress " + serverToJoin->address + "\n"; - launchScript += "serverPort " + QString::number(serverToJoin->port) + "\n"; + if (targetToJoin) { + if (!targetToJoin->address.isEmpty()) { + launchScript += "serverAddress " + targetToJoin->address + "\n"; + launchScript += "serverPort " + QString::number(targetToJoin->port) + "\n"; + } else if (!targetToJoin->world.isEmpty()) { + launchScript += "worldName " + targetToJoin->world + "\n"; + } } // generic minecraft params @@ -787,13 +795,11 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS return launchScript; } -QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) +QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) { QStringList out; - out << "Main Class:" - << " " + getMainClass() << ""; - out << "Native path:" - << " " + getNativePath() << ""; + out << "Main Class:" << " " + getMainClass() << ""; + out << "Native path:" << " " + getNativePath() << ""; auto profile = m_components->getProfile(); @@ -884,7 +890,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << ""; } - auto params = processMinecraftArgs(nullptr, serverToJoin); + auto params = processMinecraftArgs(nullptr, targetToJoin); out << "Params:"; out << " " + params.join(' '); out << ""; @@ -1034,7 +1040,7 @@ Task::Ptr MinecraftInstance::createUpdateTask(Net::Mode mode) return nullptr; } -shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) +shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) { updateRuntimeContext(); // FIXME: get rid of shared_from_this ... @@ -1058,16 +1064,23 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(makeShared(pptr)); } - if (!serverToJoin && settings()->get("JoinServerOnLaunch").toBool()) { + if (!targetToJoin && settings()->get("JoinOnLaunch").toBool()) { QString fullAddress = settings()->get("JoinServerOnLaunchAddress").toString(); - serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(fullAddress))); + if (!fullAddress.isEmpty()) { + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(fullAddress, false))); + } else { + QString world = settings()->get("JoinWorldOnLaunch").toString(); + if (!world.isEmpty()) { + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(world, true))); + } + } } - if (serverToJoin && serverToJoin->port == 25565) { + if (targetToJoin && targetToJoin->port == 25565) { // Resolve server address to join on launch auto step = makeShared(pptr); - step->setLookupAddress(serverToJoin->address); - step->setOutputAddressPtr(serverToJoin); + step->setLookupAddress(targetToJoin->address); + step->setOutputAddressPtr(targetToJoin); process->appendStep(step); } @@ -1100,7 +1113,7 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt // print some instance info here... { - process->appendStep(makeShared(pptr, session, serverToJoin)); + process->appendStep(makeShared(pptr, session, targetToJoin)); } // extract native jars if needed @@ -1123,7 +1136,7 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt auto step = makeShared(pptr); step->setWorkingDirectory(gameRoot()); step->setAuthSession(session); - step->setServerToJoin(serverToJoin); + step->setTargetToJoin(targetToJoin); process->appendStep(step); } diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 7af0df389..ad2cda186 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -39,7 +39,7 @@ #include #include #include "BaseInstance.h" -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" #include "minecraft/mod/Mod.h" class ModFolderModel; @@ -56,7 +56,7 @@ class MinecraftInstance : public BaseInstance { Q_OBJECT public: MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir); - virtual ~MinecraftInstance() {}; + virtual ~MinecraftInstance() = default; virtual void saveNow() override; void loadSpecificSettings() override; @@ -121,11 +121,11 @@ class MinecraftInstance : public BaseInstance { ////// Launch stuff ////// Task::Ptr createUpdateTask(Net::Mode mode) override; - shared_qobject_ptr createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override; + shared_qobject_ptr createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) override; QStringList extraArguments() override; - QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override; + QStringList verboseDescription(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) override; QList getJarMods() const; - QString createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin); + QString createLaunchScript(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin); /// get arguments passed to java QStringList javaArguments(); QString getLauncher(); @@ -155,7 +155,7 @@ class MinecraftInstance : public BaseInstance { virtual QString getMainClass() const; // FIXME: remove - virtual QStringList processMinecraftArgs(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) const; + virtual QStringList processMinecraftArgs(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) const; virtual JavaVersion getJavaVersion(); diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index b35d55924..be1bde464 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -90,7 +90,7 @@ void LauncherPartLaunch::executeTask() } } - m_launchScript = minecraftInstance->createLaunchScript(m_session, m_serverToJoin); + m_launchScript = minecraftInstance->createLaunchScript(m_session, m_target_to_join); QStringList args = minecraftInstance->javaArguments(); QString allArgs = args.join(", "); emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::Launcher); diff --git a/launcher/minecraft/launch/LauncherPartLaunch.h b/launcher/minecraft/launch/LauncherPartLaunch.h index fcd4daec6..ca0906550 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.h +++ b/launcher/minecraft/launch/LauncherPartLaunch.h @@ -19,13 +19,13 @@ #include #include -#include "MinecraftServerTarget.h" +#include "MinecraftTarget.h" class LauncherPartLaunch : public LaunchStep { Q_OBJECT public: explicit LauncherPartLaunch(LaunchTask* parent); - virtual ~LauncherPartLaunch() {}; + virtual ~LauncherPartLaunch() = default; virtual void executeTask(); virtual bool abort(); @@ -34,7 +34,7 @@ class LauncherPartLaunch : public LaunchStep { void setWorkingDirectory(const QString& wd); void setAuthSession(AuthSessionPtr session) { m_session = session; } - void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { m_serverToJoin = std::move(serverToJoin); } + void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_target_to_join = std::move(targetToJoin); } private slots: void on_state(LoggedProcess::State state); @@ -44,7 +44,7 @@ class LauncherPartLaunch : public LaunchStep { QString m_command; AuthSessionPtr m_session; QString m_launchScript; - MinecraftServerTargetPtr m_serverToJoin; + MinecraftTarget::Ptr m_target_to_join; bool mayProceed = false; }; diff --git a/launcher/minecraft/launch/MinecraftServerTarget.cpp b/launcher/minecraft/launch/MinecraftTarget.cpp similarity index 86% rename from launcher/minecraft/launch/MinecraftServerTarget.cpp rename to launcher/minecraft/launch/MinecraftTarget.cpp index e201efab1..ba9f87511 100644 --- a/launcher/minecraft/launch/MinecraftServerTarget.cpp +++ b/launcher/minecraft/launch/MinecraftTarget.cpp @@ -13,13 +13,18 @@ * limitations under the License. */ -#include "MinecraftServerTarget.h" +#include "MinecraftTarget.h" #include // FIXME: the way this is written, it can't ever do any sort of validation and can accept total junk -MinecraftServerTarget MinecraftServerTarget::parse(const QString& fullAddress) +MinecraftTarget MinecraftTarget::parse(const QString& fullAddress, bool useWorld) { + if (useWorld) { + MinecraftTarget target; + target.world = fullAddress; + return target; + } QStringList split = fullAddress.split(":"); // The logic below replicates the exact logic minecraft uses for parsing server addresses. @@ -56,5 +61,5 @@ MinecraftServerTarget MinecraftServerTarget::parse(const QString& fullAddress) } } - return MinecraftServerTarget{ realAddress, realPort }; + return MinecraftTarget{ realAddress, realPort }; } diff --git a/launcher/minecraft/launch/MinecraftServerTarget.h b/launcher/minecraft/launch/MinecraftTarget.h similarity index 80% rename from launcher/minecraft/launch/MinecraftServerTarget.h rename to launcher/minecraft/launch/MinecraftTarget.h index 2edd8a30d..7f8b268d9 100644 --- a/launcher/minecraft/launch/MinecraftServerTarget.h +++ b/launcher/minecraft/launch/MinecraftTarget.h @@ -19,11 +19,11 @@ #include -struct MinecraftServerTarget { +struct MinecraftTarget { QString address; quint16 port; - static MinecraftServerTarget parse(const QString& fullAddress); + QString world; + static MinecraftTarget parse(const QString& fullAddress, bool useWorld); + using Ptr = std::shared_ptr; }; - -using MinecraftServerTargetPtr = std::shared_ptr; diff --git a/launcher/minecraft/launch/PrintInstanceInfo.cpp b/launcher/minecraft/launch/PrintInstanceInfo.cpp index e3a45b030..78cb26378 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.cpp +++ b/launcher/minecraft/launch/PrintInstanceInfo.cpp @@ -129,6 +129,6 @@ void PrintInstanceInfo::executeTask() #endif logLines(log, MessageLevel::Launcher); - logLines(instance->verboseDescription(m_session, m_serverToJoin), MessageLevel::Launcher); + logLines(instance->verboseDescription(m_session, m_target_to_join), MessageLevel::Launcher); emitSucceeded(); } diff --git a/launcher/minecraft/launch/PrintInstanceInfo.h b/launcher/minecraft/launch/PrintInstanceInfo.h index 93c5f0fd6..780ac5b2c 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.h +++ b/launcher/minecraft/launch/PrintInstanceInfo.h @@ -16,22 +16,21 @@ #pragma once #include -#include #include "minecraft/auth/AuthSession.h" -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" // FIXME: temporary wrapper for existing task. class PrintInstanceInfo : public LaunchStep { Q_OBJECT public: - explicit PrintInstanceInfo(LaunchTask* parent, AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) - : LaunchStep(parent), m_session(session), m_serverToJoin(serverToJoin) {}; - virtual ~PrintInstanceInfo() {}; + explicit PrintInstanceInfo(LaunchTask* parent, AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) + : LaunchStep(parent), m_session(session), m_target_to_join(targetToJoin) {}; + virtual ~PrintInstanceInfo() = default; virtual void executeTask(); virtual bool canAbort() const { return false; } private: AuthSessionPtr m_session; - MinecraftServerTargetPtr m_serverToJoin; + MinecraftTarget::Ptr m_target_to_join; }; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 76add9402..a017d5e13 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -36,6 +36,8 @@ */ #include "InstanceSettingsPage.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/WorldList.h" #include "ui_InstanceSettingsPage.h" #include @@ -71,6 +73,22 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance* inst, QWidget* parent) connect(ui->useNativeGLFWCheck, &QAbstractButton::toggled, this, &InstanceSettingsPage::onUseNativeGLFWChanged); connect(ui->useNativeOpenALCheck, &QAbstractButton::toggled, this, &InstanceSettingsPage::onUseNativeOpenALChanged); + auto mInst = dynamic_cast(inst); + m_world_quickplay_supported = mInst && mInst->traits().contains("feature:is_quick_play_singleplayer"); + if (m_world_quickplay_supported) { + auto worlds = mInst->worldList(); + worlds->update(); + for (const auto& world : worlds->allWorlds()) { + ui->worldsCb->addItem(world.folderName()); + } + } else { + ui->worldsCb->hide(); + ui->worldJoinButton->hide(); + ui->serverJoinAddressButton->setChecked(true); + ui->serverJoinAddress->setEnabled(true); + ui->serverJoinAddressButton->setStyleSheet("QRadioButton::indicator { width: 0px; height: 0px; }"); + } + loadSettings(); updateThresholds(); @@ -256,9 +274,16 @@ void InstanceSettingsPage::applySettings() bool joinServerOnLaunch = ui->serverJoinGroupBox->isChecked(); m_settings->set("JoinServerOnLaunch", joinServerOnLaunch); if (joinServerOnLaunch) { - m_settings->set("JoinServerOnLaunchAddress", ui->serverJoinAddress->text()); + if (ui->serverJoinAddressButton->isChecked() || !m_world_quickplay_supported) { + m_settings->set("JoinServerOnLaunchAddress", ui->serverJoinAddress->text()); + m_settings->reset("JoinWorldOnLaunch"); + } else { + m_settings->set("JoinWorldOnLaunch", ui->worldsCb->currentText()); + m_settings->reset("JoinServerOnLaunchAddress"); + } } else { m_settings->reset("JoinServerOnLaunchAddress"); + m_settings->reset("JoinWorldOnLaunch"); } // Use an account for this instance @@ -379,7 +404,25 @@ void InstanceSettingsPage::loadSettings() ui->recordGameTime->setChecked(m_settings->get("RecordGameTime").toBool()); ui->serverJoinGroupBox->setChecked(m_settings->get("JoinServerOnLaunch").toBool()); - ui->serverJoinAddress->setText(m_settings->get("JoinServerOnLaunchAddress").toString()); + + if (auto server = m_settings->get("JoinServerOnLaunchAddress").toString(); !server.isEmpty()) { + ui->serverJoinAddress->setText(server); + ui->serverJoinAddressButton->setChecked(true); + ui->worldJoinButton->setChecked(false); + ui->serverJoinAddress->setEnabled(true); + ui->worldsCb->setEnabled(false); + } else if (auto world = m_settings->get("JoinWorldOnLaunch").toString(); !world.isEmpty() && m_world_quickplay_supported) { + ui->worldsCb->setCurrentText(world); + ui->serverJoinAddressButton->setChecked(false); + ui->worldJoinButton->setChecked(true); + ui->serverJoinAddress->setEnabled(false); + ui->worldsCb->setEnabled(true); + } else { + ui->serverJoinAddressButton->setChecked(true); + ui->worldJoinButton->setChecked(false); + ui->serverJoinAddress->setEnabled(true); + ui->worldsCb->setEnabled(false); + } ui->instanceAccountGroupBox->setChecked(m_settings->get("UseAccountForInstance").toBool()); updateAccountsMenu(); @@ -534,3 +577,13 @@ void InstanceSettingsPage::updateThresholds() ui->labelMaxMemIcon->setPixmap(pix); } } + +void InstanceSettingsPage::on_serverJoinAddressButton_toggled(bool checked) +{ + ui->serverJoinAddress->setEnabled(checked); +} + +void InstanceSettingsPage::on_worldJoinButton_toggled(bool checked) +{ + ui->worldsCb->setEnabled(checked); +} diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 8b78dcb7f..6364502c9 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -70,6 +70,8 @@ class InstanceSettingsPage : public QWidget, public BasePage { void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); void on_maxMemSpinBox_valueChanged(int i); + void on_serverJoinAddressButton_toggled(bool checked); + void on_worldJoinButton_toggled(bool checked); void onUseNativeGLFWChanged(bool checked); void onUseNativeOpenALChanged(bool checked); @@ -90,4 +92,5 @@ class InstanceSettingsPage : public QWidget, public BasePage { BaseInstance* m_instance; SettingsObjectPtr m_settings; unique_qobject_ptr checker; + bool m_world_quickplay_supported; }; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 9490860ae..2f496318d 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -660,7 +660,7 @@ - Set a server to join on launch + Set a target to join on launch true @@ -668,26 +668,26 @@ false - - - - - - - - 0 - 0 - - - - Server address: - - - - - - - + + + + + Server address: + + + + + + + + + + Singleplayer world + + + + + diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index f842b4b93..d8035e73e 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -168,7 +168,7 @@ class ServersModel : public QAbstractListModel { m_saveTimer.setInterval(5000); connect(&m_saveTimer, &QTimer::timeout, this, &ServersModel::save_internal); } - virtual ~ServersModel() {}; + virtual ~ServersModel() = default; void observe() { @@ -731,7 +731,7 @@ void ServersPage::on_actionMove_Down_triggered() void ServersPage::on_actionJoin_triggered() { const auto& address = m_model->at(currentServer)->m_address; - APPLICATION->launch(m_inst, true, false, std::make_shared(MinecraftServerTarget::parse(address))); + APPLICATION->launch(m_inst, true, false, std::make_shared(MinecraftTarget::parse(address, false))); } #include "ServersPage.moc" diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index 4f30e4bb7..548d1025e 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -82,7 +82,7 @@ class WorldListProxyModel : public QSortFilterProxyModel { } }; -WorldListPage::WorldListPage(BaseInstance* inst, std::shared_ptr worlds, QWidget* parent) +WorldListPage::WorldListPage(InstancePtr inst, std::shared_ptr worlds, QWidget* parent) : QMainWindow(parent), m_inst(inst), ui(new Ui::WorldListPage), m_worlds(worlds) { ui->setupUi(this); @@ -120,6 +120,8 @@ void WorldListPage::openedImpl() m_wide_bar_setting = APPLICATION->settings()->getSetting(setting_name); ui->toolBar->setVisibilityState(m_wide_bar_setting->get().toByteArray()); + auto mInst = std::dynamic_pointer_cast(m_inst); + ui->toolBar->setActionVisible(ui->actionJoin, mInst && mInst->traits().contains("feature:is_quick_play_singleplayer")); } void WorldListPage::closedImpl() @@ -339,6 +341,9 @@ void WorldListPage::worldChanged([[maybe_unused]] const QModelIndex& current, [[ ui->actionDatapacks->setEnabled(enable); bool hasIcon = !index.data(WorldList::IconFileRole).isNull(); ui->actionReset_Icon->setEnabled(enable && hasIcon); + auto mInst = std::dynamic_pointer_cast(m_inst); + ui->actionJoin->setEnabled(enable); + ui->toolBar->setActionVisible(ui->actionJoin, mInst && mInst->traits().contains("feature:is_quick_play_singleplayer")); } void WorldListPage::on_actionAdd_triggered() @@ -418,4 +423,15 @@ void WorldListPage::on_actionRefresh_triggered() m_worlds->update(); } +void WorldListPage::on_actionJoin_triggered() +{ + QModelIndex index = getSelectedWorld(); + if (!index.isValid()) { + return; + } + auto worldVariant = m_worlds->data(index, WorldList::ObjectRole); + auto world = (World*)worldVariant.value(); + APPLICATION->launch(m_inst, true, false, std::make_shared(MinecraftTarget::parse(world->folderName(), true))); +} + #include "WorldListPage.moc" diff --git a/launcher/ui/pages/instance/WorldListPage.h b/launcher/ui/pages/instance/WorldListPage.h index 4f83002f4..84d9cd075 100644 --- a/launcher/ui/pages/instance/WorldListPage.h +++ b/launcher/ui/pages/instance/WorldListPage.h @@ -53,7 +53,7 @@ class WorldListPage : public QMainWindow, public BasePage { Q_OBJECT public: - explicit WorldListPage(BaseInstance* inst, std::shared_ptr worlds, QWidget* parent = 0); + explicit WorldListPage(InstancePtr inst, std::shared_ptr worlds, QWidget* parent = 0); virtual ~WorldListPage(); virtual QString displayName() const override { return tr("Worlds"); } @@ -72,7 +72,7 @@ class WorldListPage : public QMainWindow, public BasePage { QMenu* createPopupMenu() override; protected: - BaseInstance* m_inst; + InstancePtr m_inst; private: QModelIndex getSelectedWorld(); @@ -101,6 +101,7 @@ class WorldListPage : public QMainWindow, public BasePage { void on_actionReset_Icon_triggered(); void worldChanged(const QModelIndex& current, const QModelIndex& previous); void mceditState(LoggedProcess::State state); + void on_actionJoin_triggered(); void ShowContextMenu(const QPoint& pos); }; diff --git a/launcher/ui/pages/instance/WorldListPage.ui b/launcher/ui/pages/instance/WorldListPage.ui index d74dd0796..04344b453 100644 --- a/launcher/ui/pages/instance/WorldListPage.ui +++ b/launcher/ui/pages/instance/WorldListPage.ui @@ -81,6 +81,7 @@ + @@ -97,6 +98,11 @@ Add + + + Join + + Rename diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index 46caaaef2..455b14f69 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -309,4 +309,17 @@ bool WideBar::checkHash(QByteArray const& old_hash) const return old_hash == getHash(); } +void WideBar::setActionVisible(QAction* action, bool visible) +{ + auto iter = getMatching(action); + if (iter == m_entries.end()) { + return; + } + + iter->bar_action->setVisible(visible); + + // NOTE: This is needed so that disabled actions get reflected on the button when it is made visible. + static_cast(widgetForAction(iter->bar_action))->actionChanged(); +} + #include "WideBar.moc" diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index c47f3a596..09480594a 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -38,6 +38,8 @@ class WideBar : public QToolBar { [[nodiscard]] QByteArray getVisibilityState() const; void setVisibilityState(QByteArray&&); + void setActionVisible(QAction* action, bool visible); + private: struct BarEntry { enum class Type { None, Action, Separator, Spacer } type = Type::None; diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java b/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java index de28a0401..a5f027ba6 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java +++ b/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java @@ -70,7 +70,7 @@ public abstract class AbstractLauncher implements Launcher { // secondary parameters protected final int width, height; protected final boolean maximize; - protected final String serverAddress, serverPort; + protected final String serverAddress, serverPort, worldName; protected final String mainClassName; @@ -80,6 +80,7 @@ public abstract class AbstractLauncher implements Launcher { serverAddress = params.getString("serverAddress", null); serverPort = params.getString("serverPort", null); + worldName = params.getString("worldName", null); String windowParams = params.getString("windowParams", null); diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java b/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java index 49e5d518f..dc518be64 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java +++ b/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java @@ -62,13 +62,15 @@ import java.util.Collections; import java.util.List; public final class StandardLauncher extends AbstractLauncher { - private final boolean quickPlaySupported; + private final boolean quickPlayMultiplayerSupported; + private final boolean quickPlaySingleplayerSupported; public StandardLauncher(Parameters params) { super(params); List traits = params.getList("traits", Collections.emptyList()); - quickPlaySupported = traits.contains("feature:is_quick_play_multiplayer"); + quickPlayMultiplayerSupported = traits.contains("feature:is_quick_play_multiplayer"); + quickPlaySingleplayerSupported = traits.contains("feature:is_quick_play_singleplayer"); } @Override @@ -83,7 +85,7 @@ public final class StandardLauncher extends AbstractLauncher { } if (serverAddress != null) { - if (quickPlaySupported) { + if (quickPlayMultiplayerSupported) { // as of 23w14a gameArgs.add("--quickPlayMultiplayer"); gameArgs.add(serverAddress + ':' + serverPort); @@ -93,6 +95,9 @@ public final class StandardLauncher extends AbstractLauncher { gameArgs.add("--port"); gameArgs.add(serverPort); } + } else if (worldName != null && quickPlaySingleplayerSupported) { + gameArgs.add("--quickPlaySingleplayer"); + gameArgs.add(worldName); } // find and invoke the main method From a9c7e95c6652bc965fc1a4e8097cd4be22a3df23 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Aug 2024 19:39:32 +0300 Subject: [PATCH 19/26] fix widebar action removal Signed-off-by: Trial97 --- launcher/ui/pages/instance/WorldListPage.cpp | 16 ++++++++++++---- launcher/ui/widgets/WideBar.cpp | 12 +++++------- launcher/ui/widgets/WideBar.h | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index 548d1025e..4ed5f1f73 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -113,6 +113,11 @@ void WorldListPage::openedImpl() { m_worlds->startWatching(); + auto mInst = std::dynamic_pointer_cast(m_inst); + if (!mInst || !mInst->traits().contains("feature:is_quick_play_singleplayer")) { + ui->toolBar->removeAction(ui->actionJoin); + } + auto const setting_name = QString("WideBarVisibility_%1").arg(id()); if (!APPLICATION->settings()->contains(setting_name)) m_wide_bar_setting = APPLICATION->settings()->registerSetting(setting_name); @@ -120,8 +125,6 @@ void WorldListPage::openedImpl() m_wide_bar_setting = APPLICATION->settings()->getSetting(setting_name); ui->toolBar->setVisibilityState(m_wide_bar_setting->get().toByteArray()); - auto mInst = std::dynamic_pointer_cast(m_inst); - ui->toolBar->setActionVisible(ui->actionJoin, mInst && mInst->traits().contains("feature:is_quick_play_singleplayer")); } void WorldListPage::closedImpl() @@ -341,9 +344,14 @@ void WorldListPage::worldChanged([[maybe_unused]] const QModelIndex& current, [[ ui->actionDatapacks->setEnabled(enable); bool hasIcon = !index.data(WorldList::IconFileRole).isNull(); ui->actionReset_Icon->setEnabled(enable && hasIcon); + auto mInst = std::dynamic_pointer_cast(m_inst); - ui->actionJoin->setEnabled(enable); - ui->toolBar->setActionVisible(ui->actionJoin, mInst && mInst->traits().contains("feature:is_quick_play_singleplayer")); + auto supportsJoin = mInst && mInst->traits().contains("feature:is_quick_play_singleplayer"); + ui->actionJoin->setEnabled(enable && supportsJoin); + + if (!supportsJoin) { + ui->toolBar->removeAction(ui->actionJoin); + } } void WorldListPage::on_actionAdd_triggered() diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index 455b14f69..2940d7ce7 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -309,17 +309,15 @@ bool WideBar::checkHash(QByteArray const& old_hash) const return old_hash == getHash(); } -void WideBar::setActionVisible(QAction* action, bool visible) +void WideBar::removeAction(QAction* action) { auto iter = getMatching(action); - if (iter == m_entries.end()) { + if (iter == m_entries.end()) return; - } - iter->bar_action->setVisible(visible); - - // NOTE: This is needed so that disabled actions get reflected on the button when it is made visible. - static_cast(widgetForAction(iter->bar_action))->actionChanged(); + iter->bar_action->setVisible(false); + removeAction(iter->bar_action); + m_entries.erase(iter); } #include "WideBar.moc" diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index 09480594a..f4877a89a 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -38,7 +38,7 @@ class WideBar : public QToolBar { [[nodiscard]] QByteArray getVisibilityState() const; void setVisibilityState(QByteArray&&); - void setActionVisible(QAction* action, bool visible); + void removeAction(QAction* action); private: struct BarEntry { From dcca175b364498494623cbe436ab4b926e12bd34 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 9 Aug 2024 11:06:31 +0300 Subject: [PATCH 20/26] snake_case to m_camelCase Signed-off-by: Trial97 --- launcher/Application.cpp | 34 +++++++++---------- launcher/Application.h | 4 +-- launcher/LaunchController.cpp | 2 +- launcher/LaunchController.h | 4 +-- launcher/minecraft/MinecraftInstance.cpp | 6 ++++ .../minecraft/launch/LauncherPartLaunch.cpp | 2 +- .../minecraft/launch/LauncherPartLaunch.h | 4 +-- .../minecraft/launch/PrintInstanceInfo.cpp | 2 +- launcher/minecraft/launch/PrintInstanceInfo.h | 4 +-- 9 files changed, 34 insertions(+), 28 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 84b759e09..2137ed091 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -250,8 +250,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) parser.process(arguments()); m_instanceIdToLaunch = parser.value("launch"); - m_server_to_join = parser.value("server"); - m_world_to_join = parser.value("world"); + m_serverToJoin = parser.value("server"); + m_worldToJoin = parser.value("world"); m_profileToUse = parser.value("profile"); m_liveCheck = parser.isSet("alive"); @@ -267,7 +267,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) } // error if --launch is missing with --server or --profile - if (((!m_server_to_join.isEmpty() || !m_world_to_join.isEmpty()) || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { + if (((!m_serverToJoin.isEmpty() || !m_worldToJoin.isEmpty()) || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl; m_status = Application::Failed; return; @@ -385,10 +385,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) launch.command = "launch"; launch.args["id"] = m_instanceIdToLaunch; - if (!m_server_to_join.isEmpty()) { - launch.args["server"] = m_server_to_join; - } else if (!m_world_to_join.isEmpty()) { - launch.args["world"] = m_world_to_join; + if (!m_serverToJoin.isEmpty()) { + launch.args["server"] = m_serverToJoin; + } else if (!m_worldToJoin.isEmpty()) { + launch.args["world"] = m_worldToJoin; } if (!m_profileToUse.isEmpty()) { launch.args["profile"] = m_profileToUse; @@ -525,10 +525,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) if (!m_instanceIdToLaunch.isEmpty()) { qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch; } - if (!m_server_to_join.isEmpty()) { - qDebug() << "Address of server to join :" << m_server_to_join; - } else if (!m_world_to_join.isEmpty()) { - qDebug() << "Name of the world to join :" << m_world_to_join; + if (!m_serverToJoin.isEmpty()) { + qDebug() << "Address of server to join :" << m_serverToJoin; + } else if (!m_worldToJoin.isEmpty()) { + qDebug() << "Name of the world to join :" << m_worldToJoin; } qDebug() << "<> Paths set."; } @@ -1167,13 +1167,13 @@ void Application::performMainStartupAction() MinecraftAccountPtr accountToUse = nullptr; qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching"; - if (!m_server_to_join.isEmpty()) { + if (!m_serverToJoin.isEmpty()) { // FIXME: validate the server string - targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_server_to_join, false))); - qDebug() << " Launching with server" << m_server_to_join; - } else if (!m_world_to_join.isEmpty()) { - targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_world_to_join, true))); - qDebug() << " Launching with world" << m_world_to_join; + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_serverToJoin, false))); + qDebug() << " Launching with server" << m_serverToJoin; + } else if (!m_worldToJoin.isEmpty()) { + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_worldToJoin, true))); + qDebug() << " Launching with world" << m_worldToJoin; } if (!m_profileToUse.isEmpty()) { diff --git a/launcher/Application.h b/launcher/Application.h index fb54b1005..3bb20125e 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -289,8 +289,8 @@ class Application : public QApplication { QString m_detectedGLFWPath; QString m_detectedOpenALPath; QString m_instanceIdToLaunch; - QString m_server_to_join; - QString m_world_to_join; + QString m_serverToJoin; + QString m_worldToJoin; QString m_profileToUse; bool m_liveCheck = false; QList m_urlsToImport; diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 83bf3838e..73800574f 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -324,7 +324,7 @@ void LaunchController::launchInstance() return; } - m_launcher = m_instance->createLaunchTask(m_session, m_target_to_join); + m_launcher = m_instance->createLaunchTask(m_session, m_targetToJoin); if (!m_launcher) { emitFailed(tr("Couldn't instantiate a launcher.")); return; diff --git a/launcher/LaunchController.h b/launcher/LaunchController.h index e620b8c62..6e2a94258 100644 --- a/launcher/LaunchController.h +++ b/launcher/LaunchController.h @@ -62,7 +62,7 @@ class LaunchController : public Task { void setParentWidget(QWidget* widget) { m_parentWidget = widget; } - void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_target_to_join = std::move(targetToJoin); } + void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_targetToJoin = std::move(targetToJoin); } void setAccountToUse(MinecraftAccountPtr accountToUse) { m_accountToUse = std::move(accountToUse); } @@ -94,5 +94,5 @@ class LaunchController : public Task { MinecraftAccountPtr m_accountToUse = nullptr; AuthSessionPtr m_session; shared_qobject_ptr m_launcher; - MinecraftTarget::Ptr m_target_to_join; + MinecraftTarget::Ptr m_targetToJoin; }; diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index c50d57513..baebf8506 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -803,6 +803,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr auto profile = m_components->getProfile(); + // traits auto alltraits = traits(); if (alltraits.size()) { out << "Traits:"; @@ -812,6 +813,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << ""; } + // native libraries auto settings = this->settings(); bool nativeOpenAL = settings->get("UseNativeOpenAL").toBool(); bool nativeGLFW = settings->get("UseNativeGLFW").toBool(); @@ -847,6 +849,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << ""; } + // mods and core mods auto printModList = [&](const QString& label, ModFolderModel& model) { if (model.size()) { out << QString("%1:").arg(label); @@ -875,6 +878,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr printModList("Mods", *(loaderModList().get())); printModList("Core Mods", *(coreModList().get())); + // jar mods auto& jarMods = profile->getJarMods(); if (jarMods.size()) { out << "Jar Mods:"; @@ -890,11 +894,13 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << ""; } + // minecraft arguments auto params = processMinecraftArgs(nullptr, targetToJoin); out << "Params:"; out << " " + params.join(' '); out << ""; + // window size QString windowParams; if (settings->get("LaunchMaximized").toBool()) { out << "Window size: max (if available)"; diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index be1bde464..2b932ae47 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -90,7 +90,7 @@ void LauncherPartLaunch::executeTask() } } - m_launchScript = minecraftInstance->createLaunchScript(m_session, m_target_to_join); + m_launchScript = minecraftInstance->createLaunchScript(m_session, m_targetToJoin); QStringList args = minecraftInstance->javaArguments(); QString allArgs = args.join(", "); emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::Launcher); diff --git a/launcher/minecraft/launch/LauncherPartLaunch.h b/launcher/minecraft/launch/LauncherPartLaunch.h index ca0906550..ea125aa9e 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.h +++ b/launcher/minecraft/launch/LauncherPartLaunch.h @@ -34,7 +34,7 @@ class LauncherPartLaunch : public LaunchStep { void setWorkingDirectory(const QString& wd); void setAuthSession(AuthSessionPtr session) { m_session = session; } - void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_target_to_join = std::move(targetToJoin); } + void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_targetToJoin = std::move(targetToJoin); } private slots: void on_state(LoggedProcess::State state); @@ -44,7 +44,7 @@ class LauncherPartLaunch : public LaunchStep { QString m_command; AuthSessionPtr m_session; QString m_launchScript; - MinecraftTarget::Ptr m_target_to_join; + MinecraftTarget::Ptr m_targetToJoin; bool mayProceed = false; }; diff --git a/launcher/minecraft/launch/PrintInstanceInfo.cpp b/launcher/minecraft/launch/PrintInstanceInfo.cpp index 78cb26378..e44d09839 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.cpp +++ b/launcher/minecraft/launch/PrintInstanceInfo.cpp @@ -129,6 +129,6 @@ void PrintInstanceInfo::executeTask() #endif logLines(log, MessageLevel::Launcher); - logLines(instance->verboseDescription(m_session, m_target_to_join), MessageLevel::Launcher); + logLines(instance->verboseDescription(m_session, m_targetToJoin), MessageLevel::Launcher); emitSucceeded(); } diff --git a/launcher/minecraft/launch/PrintInstanceInfo.h b/launcher/minecraft/launch/PrintInstanceInfo.h index 780ac5b2c..4138c0cd2 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.h +++ b/launcher/minecraft/launch/PrintInstanceInfo.h @@ -24,7 +24,7 @@ class PrintInstanceInfo : public LaunchStep { Q_OBJECT public: explicit PrintInstanceInfo(LaunchTask* parent, AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) - : LaunchStep(parent), m_session(session), m_target_to_join(targetToJoin) {}; + : LaunchStep(parent), m_session(session), m_targetToJoin(targetToJoin) {}; virtual ~PrintInstanceInfo() = default; virtual void executeTask(); @@ -32,5 +32,5 @@ class PrintInstanceInfo : public LaunchStep { private: AuthSessionPtr m_session; - MinecraftTarget::Ptr m_target_to_join; + MinecraftTarget::Ptr m_targetToJoin; }; From c2192cfa987769375435f8f97e8a60cb46b5930f Mon Sep 17 00:00:00 2001 From: Tianhao Chai Date: Fri, 9 Aug 2024 14:11:44 -0400 Subject: [PATCH 21/26] mangohud support: getLibraryString should return absolute path when possible Some distros ship MangoHub vulkan layer json with bare shared object name instead of an absolute path. This breaks environment config as `MinecraftInstance::createLaunchEnvironment()` seems to require absolute path of `libMangoHud.so`. Since we already have `MangoHud::findLibrary()` lying around, use that to figure out where `libMangoHud.so` really is. In case of a platform that doesn't support `dlopen()`, fallback to old behavior and return the path verbatim as it is recorded in vk layer json. Signed-off-by: Tianhao Chai --- launcher/MangoHud.cpp | 30 +++++++++++++++++------- launcher/minecraft/MinecraftInstance.cpp | 2 +- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/launcher/MangoHud.cpp b/launcher/MangoHud.cpp index ab79f418b..ba16ddc4a 100644 --- a/launcher/MangoHud.cpp +++ b/launcher/MangoHud.cpp @@ -40,8 +40,8 @@ namespace MangoHud { QString getLibraryString() { - /* - * Check for vulkan layers in this order: + /** + * Guess MangoHud install location by searching for vulkan layers in this order: * * $VK_LAYER_PATH * $XDG_DATA_DIRS (/usr/local/share/:/usr/share/) @@ -49,8 +49,9 @@ QString getLibraryString() * /etc * $XDG_CONFIG_DIRS (/etc/xdg) * $XDG_CONFIG_HOME (~/.config) + * + * @returns Absolute path of libMangoHud.so if found and empty QString otherwise. */ - QStringList vkLayerList; { QString home = QDir::homePath(); @@ -85,7 +86,7 @@ QString getLibraryString() vkLayerList << FS::PathCombine(xdgConfigHome, "vulkan", "implicit_layer.d"); } - for (QString vkLayer : vkLayerList) { + for (const QString& vkLayer : vkLayerList) { // prefer to use architecture specific vulkan layers QString currentArch = QSysInfo::currentCpuArchitecture(); @@ -95,8 +96,8 @@ QString getLibraryString() QStringList manifestNames = { QString("MangoHud.%1.json").arg(currentArch), "MangoHud.json" }; - QString filePath = ""; - for (QString manifestName : manifestNames) { + QString filePath{}; + for (const QString& manifestName : manifestNames) { QString tryPath = FS::PathCombine(vkLayer, manifestName); if (QFile::exists(tryPath)) { filePath = tryPath; @@ -111,10 +112,23 @@ QString getLibraryString() auto conf = Json::requireDocument(filePath, vkLayer); auto confObject = Json::requireObject(conf, vkLayer); auto layer = Json::ensureObject(confObject, "layer"); - return Json::ensureString(layer, "library_path"); + QString libraryName = Json::ensureString(layer, "library_path"); + +#ifdef __GLIBC__ + // Check whether mangohud is usable on a glibc based system + if (!libraryName.isEmpty()) { + QString libraryPath = findLibrary(libraryName); + if (!libraryPath.isEmpty()) { + return libraryPath; + } + } +#else + // Without glibc return recorded shared library as-is. + return libraryName; +#endif } - return QString(); + return {}; } QString findLibrary(QString libName) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index d119104fe..6befad5d6 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -608,7 +608,7 @@ QProcessEnvironment MinecraftInstance::createLaunchEnvironment() // dlsym variant is only needed for OpenGL and not included in the vulkan layer appendLib("libMangoHud_dlsym.so"); appendLib("libMangoHud_opengl.so"); - appendLib(mangoHudLib.fileName()); + preloadList << mangoHudLibString; } env.insert("LD_PRELOAD", preloadList.join(QLatin1String(":"))); From 96dad63173667456e731bad3727e79fc7ee35c8e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 11 Aug 2024 00:22:53 +0000 Subject: [PATCH 22/26] 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/9227223f6d922fee3c7b190b2cc238a99527bbb7?narHash=sha256-pQMhCCHyQGRzdfAkdJ4cIWiw%2BJNuWsTX7f0ZYSyz0VY%3D' (2024-07-03) → 'github:hercules-ci/flake-parts/8471fe90ad337a8074e957b69ca4d0089218391d?narHash=sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC%2Bx4%3D' (2024-08-01) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/7e7c39ea35c5cdd002cd4588b03a3fb9ece6fad9?narHash=sha256-EYekUHJE2gxeo2pM/zM9Wlqw1Uw2XTJXOSAO79ksc4Y%3D' (2024-07-12) → 'github:NixOS/nixpkgs/5e0ca22929f3342b19569b21b2f3462f053e497b?narHash=sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI%3D' (2024-08-09) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/8d6a17d0cdf411c55f12602624df6368ad86fac1?narHash=sha256-ni/87oHPZm6Gv0ECYxr1f6uxB0UKBWJ6HvS7lwLU6oY%3D' (2024-07-09) → 'github:cachix/pre-commit-hooks.nix/c7012d0c18567c889b948781bc74a501e92275d1?narHash=sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q%3D' (2024-08-09) --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 38b0d7430..1708a1e0a 100644 --- a/flake.lock +++ b/flake.lock @@ -23,11 +23,11 @@ ] }, "locked": { - "lastModified": 1719994518, - "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { @@ -75,11 +75,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1720768451, - "narHash": "sha256-EYekUHJE2gxeo2pM/zM9Wlqw1Uw2XTJXOSAO79ksc4Y=", + "lastModified": 1723175592, + "narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7e7c39ea35c5cdd002cd4588b03a3fb9ece6fad9", + "rev": "5e0ca22929f3342b19569b21b2f3462f053e497b", "type": "github" }, "original": { @@ -103,11 +103,11 @@ ] }, "locked": { - "lastModified": 1720524665, - "narHash": "sha256-ni/87oHPZm6Gv0ECYxr1f6uxB0UKBWJ6HvS7lwLU6oY=", + "lastModified": 1723202784, + "narHash": "sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "8d6a17d0cdf411c55f12602624df6368ad86fac1", + "rev": "c7012d0c18567c889b948781bc74a501e92275d1", "type": "github" }, "original": { From 6de026bfcf9cd29220e4d7f4a61cecacea86ad5d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 16 Aug 2024 14:34:28 +0300 Subject: [PATCH 23/26] replaced currentTextChanged with currentIndexChanged Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourcePage.cpp | 9 ++------- launcher/ui/pages/modplatform/ResourcePage.h | 2 +- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 6 +++--- launcher/ui/pages/modplatform/flame/FlamePage.h | 2 +- .../ui/pages/modplatform/flame/FlameResourcePages.cpp | 8 ++++---- launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp | 6 +++--- launcher/ui/pages/modplatform/modrinth/ModrinthPage.h | 2 +- .../pages/modplatform/modrinth/ModrinthResourcePages.cpp | 8 ++++---- 8 files changed, 19 insertions(+), 24 deletions(-) diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 4d01fb1f0..bed118465 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -321,14 +321,9 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI updateUi(); } -void ResourcePage::onVersionSelectionChanged(QString versionData) +void ResourcePage::onVersionSelectionChanged(int index) { - if (versionData.isNull() || versionData.isEmpty()) { - m_selected_version_index = -1; - return; - } - - m_selected_version_index = m_ui->versionSelectionBox->currentData().toInt(); + m_selected_version_index = index; updateSelectionButton(); } diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index d5214dd34..b625240eb 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -89,7 +89,7 @@ class ResourcePage : public QWidget, public BasePage { virtual void triggerSearch() = 0; void onSelectionChanged(QModelIndex first, QModelIndex second); - void onVersionSelectionChanged(QString data); + void onVersionSelectionChanged(int index); void onResourceSelected(); // NOTE: Can't use [[nodiscard]] here because of https://bugreports.qt.io/browse/QTBUG-58628 on Qt 5.12 diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 2c10dd085..850941269 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -84,7 +84,7 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlamePage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlamePage::onVersionSelectionChanged); + connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlamePage::onVersionSelectionChanged); ui->packView->setItemDelegate(new ProjectItemDelegate(this)); ui->packDescription->setMetaEntry("FlamePacks"); @@ -240,12 +240,12 @@ void FlamePage::suggestCurrent() [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } -void FlamePage::onVersionSelectionChanged(QString version) +void FlamePage::onVersionSelectionChanged(int index) { bool is_blocked = false; ui->versionSelectionBox->currentData().toInt(&is_blocked); - if (version.isNull() || version.isEmpty() || is_blocked) { + if (index == -1 || is_blocked) { m_selected_version_index = -1; return; } diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index d35858fbc..7590e1a95 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -78,7 +78,7 @@ class FlamePage : public QWidget, public BasePage { private slots: void triggerSearch(); void onSelectionChanged(QModelIndex first, QModelIndex second); - void onVersionSelectionChanged(QString data); + void onVersionSelectionChanged(int index); private: Ui::FlamePage* ui = nullptr; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index d82c76c3a..ffcf08b71 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -60,7 +60,7 @@ FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameModPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameModPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameModPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -94,7 +94,7 @@ FlameResourcePackPage::FlameResourcePackPage(ResourcePackDownloadDialog* dialog, // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameResourcePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameResourcePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameResourcePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -128,7 +128,7 @@ FlameTexturePackPage::FlameTexturePackPage(TexturePackDownloadDialog* dialog, Ba // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameTexturePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameTexturePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameTexturePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -162,7 +162,7 @@ FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseI // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameShaderPackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameShaderPackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameShaderPackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index cb811e428..937f8f670 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -85,7 +85,7 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthPage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthPage::onVersionSelectionChanged); + connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthPage::onVersionSelectionChanged); ui->packView->setItemDelegate(new ProjectItemDelegate(this)); ui->packDescription->setMetaEntry(metaEntryBase()); @@ -342,9 +342,9 @@ void ModrinthPage::triggerSearch() m_fetch_progress.watch(m_model->activeSearchJob().get()); } -void ModrinthPage::onVersionSelectionChanged(QString version) +void ModrinthPage::onVersionSelectionChanged(int index) { - if (version.isNull() || version.isEmpty()) { + if (index == -1) { selectedVersion = ""; return; } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index 4240dcafb..dadaeb0a0 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -80,7 +80,7 @@ class ModrinthPage : public QWidget, public BasePage { private slots: void onSelectionChanged(QModelIndex first, QModelIndex second); - void onVersionSelectionChanged(QString data); + void onVersionSelectionChanged(int index); void triggerSearch(); private: diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index 26fe46a54..6d3abca8f 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -58,7 +58,7 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instan // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthModPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthModPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthModPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -76,7 +76,7 @@ ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* d // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthResourcePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthResourcePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthResourcePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -94,7 +94,7 @@ ModrinthTexturePackPage::ModrinthTexturePackPage(TexturePackDownloadDialog* dial // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthTexturePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthTexturePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthTexturePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -112,7 +112,7 @@ ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthShaderPackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthShaderPackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthShaderPackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); From e6bc61d6d01e84e5c42ed9b779eeb1566a784a86 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 16 Aug 2024 14:44:57 +0300 Subject: [PATCH 24/26] add overload for qt5 Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 2 +- .../pages/modplatform/flame/FlameResourcePages.cpp | 11 +++++++---- .../ui/pages/modplatform/modrinth/ModrinthPage.cpp | 2 +- .../modplatform/modrinth/ModrinthResourcePages.cpp | 12 ++++++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 850941269..c8972aa2e 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -84,7 +84,7 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlamePage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlamePage::onVersionSelectionChanged); + connect(ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, &FlamePage::onVersionSelectionChanged); ui->packView->setItemDelegate(new ProjectItemDelegate(this)); ui->packDescription->setMetaEntry("FlamePacks"); diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index ffcf08b71..62c22902e 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -60,7 +60,7 @@ FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameModPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, &FlameModPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameModPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -94,7 +94,8 @@ FlameResourcePackPage::FlameResourcePackPage(ResourcePackDownloadDialog* dialog, // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameResourcePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &FlameResourcePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameResourcePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -128,7 +129,8 @@ FlameTexturePackPage::FlameTexturePackPage(TexturePackDownloadDialog* dialog, Ba // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameTexturePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &FlameTexturePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameTexturePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -162,7 +164,8 @@ FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseI // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameShaderPackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &FlameShaderPackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameShaderPackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 937f8f670..03461d85a 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -85,7 +85,7 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthPage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthPage::onVersionSelectionChanged); + connect(ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ModrinthPage::onVersionSelectionChanged); ui->packView->setItemDelegate(new ProjectItemDelegate(this)); ui->packDescription->setMetaEntry(metaEntryBase()); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index 6d3abca8f..85dcde471 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -58,7 +58,8 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instan // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthModPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ModrinthModPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthModPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -76,7 +77,8 @@ ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* d // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthResourcePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ModrinthResourcePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthResourcePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -94,7 +96,8 @@ ModrinthTexturePackPage::ModrinthTexturePackPage(TexturePackDownloadDialog* dial // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthTexturePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ModrinthTexturePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthTexturePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -112,7 +115,8 @@ ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthShaderPackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ModrinthShaderPackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthShaderPackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); From b0cd412926346496488c5e7cbfba0c2728ce2b0b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 16 Aug 2024 15:41:31 +0300 Subject: [PATCH 25/26] use index instead of currentIndex function Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index c8972aa2e..decb5de3b 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -250,7 +250,7 @@ void FlamePage::onVersionSelectionChanged(int index) return; } - m_selected_version_index = ui->versionSelectionBox->currentIndex(); + m_selected_version_index = index; Q_ASSERT(current.versions.at(m_selected_version_index).downloadUrl == ui->versionSelectionBox->currentData().toString()); From 6bd8b72f68f4dd52d746e8ffc7e503ad985fd2b0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Aug 2024 22:38:45 +0300 Subject: [PATCH 26/26] fix meta not validating for specific versions Signed-off-by: Trial97 --- launcher/meta/BaseEntity.cpp | 38 +++++++++++++++++++++++++---------- launcher/meta/Version.h | 2 +- launcher/meta/VersionList.cpp | 2 ++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 24bced3a8..b0e754ada 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -15,6 +15,7 @@ #include "BaseEntity.h" +#include "Exception.h" #include "FileSystem.h" #include "Json.h" #include "modplatform/helpers/HashUtils.h" @@ -91,7 +92,8 @@ Task::Ptr BaseEntity::loadTask(Net::Mode mode) bool BaseEntity::isLoaded() const { - return m_load_status != LoadStatus::NotLoaded; + // consider it loaded only if the main hash is either empty and was remote loadded or the hashes match and was loaded + return m_sha256.isEmpty() ? m_load_status == LoadStatus::Remote : m_load_status != LoadStatus::NotLoaded && m_sha256 == m_file_sha256; } void BaseEntity::setSha256(QString sha256) @@ -109,30 +111,44 @@ BaseEntityLoadTask::BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode) : m_e void BaseEntityLoadTask::executeTask() { const QString fname = QDir("meta").absoluteFilePath(m_entity->localFilename()); - // load local file if nothing is loaded yet - if (m_entity->m_load_status == BaseEntity::LoadStatus::NotLoaded && QFile::exists(fname)) { - setStatus(tr("Loading local file")); + auto hashMatches = false; + // the file exists on disk try to load it + if (QFile::exists(fname)) { try { - auto fileData = FS::read(fname); - m_entity->m_file_sha256 = Hashing::hash(fileData, Hashing::Algorithm::Sha256); - if (m_mode == Net::Mode::Online && !m_entity->m_sha256.isEmpty() && m_entity->m_sha256 != m_entity->m_file_sha256) { - FS::deletePath(fname); - } else { + QByteArray fileData; + // read local file if nothing is loaded yet + if (m_entity->m_load_status == BaseEntity::LoadStatus::NotLoaded || m_entity->m_file_sha256.isEmpty()) { + setStatus(tr("Loading local file")); + fileData = FS::read(fname); + m_entity->m_file_sha256 = Hashing::hash(fileData, Hashing::Algorithm::Sha256); + } + + // on online the hash needs to match + hashMatches = m_entity->m_sha256 == m_entity->m_file_sha256; + if (m_mode == Net::Mode::Online && !m_entity->m_sha256.isEmpty() && !hashMatches) { + throw Exception("mismatched checksum"); + } + + // load local file + if (m_entity->m_load_status == BaseEntity::LoadStatus::NotLoaded) { auto doc = Json::requireDocument(fileData, fname); auto obj = Json::requireObject(doc, fname); m_entity->parse(obj); m_entity->m_load_status = BaseEntity::LoadStatus::Local; } + } catch (const Exception& e) { qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause()); // just make sure it's gone and we never consider it again. FS::deletePath(fname); + m_entity->m_load_status = BaseEntity::LoadStatus::NotLoaded; } } // if we need remote update, run the update task - auto hashMatches = !m_entity->m_sha256.isEmpty() && m_entity->m_sha256 == m_entity->m_file_sha256; auto wasLoadedOffline = m_entity->m_load_status != BaseEntity::LoadStatus::NotLoaded && m_mode == Net::Mode::Offline; - if (wasLoadedOffline || hashMatches) { + // if has is not present allways fetch from remote(e.g. the main index file), else only fetch if hash doesn't match + auto wasLoadedRemote = m_entity->m_sha256.isEmpty() ? m_entity->m_load_status == BaseEntity::LoadStatus::Remote : hashMatches; + if (wasLoadedOffline || wasLoadedRemote) { emitSucceeded(); return; } diff --git a/launcher/meta/Version.h b/launcher/meta/Version.h index 149af86f6..46dc740da 100644 --- a/launcher/meta/Version.h +++ b/launcher/meta/Version.h @@ -52,7 +52,7 @@ class Version : public QObject, public BaseVersion, public BaseEntity { const Meta::RequireSet& requiredSet() const { return m_requires; } VersionFilePtr data() const { return m_data; } bool isRecommended() const { return m_recommended; } - bool isLoaded() const { return m_data != nullptr; } + bool isLoaded() const { return m_data != nullptr && BaseEntity::isLoaded(); } void merge(const Version::Ptr& other); void mergeFromList(const Version::Ptr& other); diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index f21e4594a..698c73ef4 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -139,6 +139,8 @@ Version::Ptr VersionList::getVersion(const QString& version) if (!out) { out = std::make_shared(m_uid, version); m_lookup[version] = out; + setupAddedVersion(m_versions.size(), out); + m_versions.append(out); } return out; }