Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package prismlauncher for openSUSE:Factory checked in at 2026-09-04 12:42:36 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/prismlauncher (Old) and /work/SRC/openSUSE:Factory/.prismlauncher.new.1265 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "prismlauncher" Fri Sep 4 12:42:36 2026 rev:4 rq:1375656 version:11.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/prismlauncher/prismlauncher.changes 2026-07-12 17:10:11.647343356 +0200 +++ /work/SRC/openSUSE:Factory/.prismlauncher.new.1265/prismlauncher.changes 2026-09-04 12:42:43.251453474 +0200 @@ -1,0 +2,6 @@ +Thu Sep 3 15:43:24 UTC 2026 - Илья Индиго <[email protected]> + +- Updated to 11.1.0 + * https://github.com/PrismLauncher/PrismLauncher/releases/tag/11.1.0 + +------------------------------------------------------------------- Old: ---- PrismLauncher-11.0.3.tar.gz New: ---- PrismLauncher-11.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ prismlauncher.spec ++++++ --- /var/tmp/diff_new_pack.UF0kCm/_old 2026-09-04 12:42:43.867475108 +0200 +++ /var/tmp/diff_new_pack.UF0kCm/_new 2026-09-04 12:42:43.869475178 +0200 @@ -16,9 +16,10 @@ # +%define __builder ninja %define _name PrismLauncher Name: prismlauncher -Version: 11.0.3 +Version: 11.1.0 Release: 0 Summary: A custom launcher for Minecraft License: GPL-3.0-only AND Apache-2.0 AND LGPL-3.0-only AND OFL-1.1 AND LGPL-2.1-only AND MIT AND BSD-3-Clause @@ -29,6 +30,7 @@ BuildRequires: gcc-c++ BuildRequires: hicolor-icon-theme BuildRequires: java-17-devel +BuildRequires: ninja BuildRequires: pkgconfig BuildRequires: cmake(Qt6Concurrent) BuildRequires: cmake(Qt6Core) @@ -67,6 +69,7 @@ sed -i -e 's|\$ORIGIN/||' -e 's/\${TODAY}/unknown/' CMakeLists.txt %build +export CMAKE_GENERATOR=Ninja %cmake -LA \ -DLauncher_BUILD_PLATFORM="openSUSE" \ -DLauncher_QT_VERSION_MAJOR="6" ++++++ PrismLauncher-11.0.3.tar.gz -> PrismLauncher-11.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/.github/workflows/publish.yml new/PrismLauncher-11.1.0/.github/workflows/publish.yml --- old/PrismLauncher-11.0.3/.github/workflows/publish.yml 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/.github/workflows/publish.yml 2026-09-03 08:14:38.000000000 +0200 @@ -17,7 +17,8 @@ steps: - name: Publish on Winget - uses: vedantmgoyal2009/winget-releaser@v2 + # @Octol1ttle: Pinned to a commit because no release has been published that works on ubuntu-slim + uses: vedantmgoyal2009/winget-releaser@7bd472be23763def6e16bd06cc8b1cdfab0e2fd5 # docs: add description to inputs (#335) with: identifier: PrismLauncher.PrismLauncher version: ${{ github.event.release.tag_name }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/CMakeLists.txt new/PrismLauncher-11.1.0/CMakeLists.txt --- old/PrismLauncher-11.0.3/CMakeLists.txt 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/CMakeLists.txt 2026-09-03 08:14:38.000000000 +0200 @@ -180,8 +180,8 @@ ######## Set version numbers ######## set(Launcher_VERSION_MAJOR 11) -set(Launcher_VERSION_MINOR 0) -set(Launcher_VERSION_PATCH 3) +set(Launcher_VERSION_MINOR 1) +set(Launcher_VERSION_PATCH 0) set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_PATCH}") set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_PATCH}.0") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/Application.cpp new/PrismLauncher-11.1.0/launcher/Application.cpp --- old/PrismLauncher-11.0.3/launcher/Application.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/Application.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -856,8 +856,10 @@ } { auto resetIfInvalid = [this](const Setting* setting) { - if (const QUrl url(setting->get().toString()); !url.isValid() || (url.scheme() != "http" && url.scheme() != "https")) { - m_settings->reset(setting->id()); + if (const auto value = setting->get().toString(); !value.isEmpty()) { + if (const QUrl url(value); !url.isValid() || (url.scheme() != "http" && url.scheme() != "https")) { + m_settings->reset(setting->id()); + } } }; @@ -880,16 +882,8 @@ m_settings->registerSetting("MSAClientIDOverride", ""); // Custom Flame API Key - { - m_settings->registerSetting("CFKeyOverride", ""); - m_settings->registerSetting("FlameKeyOverride", ""); - - QString flameKey = m_settings->get("CFKeyOverride").toString(); + m_settings->registerSetting({ "FlameKeyOverride", "CFKeyOverride" }, ""); - if (!flameKey.isEmpty()) - m_settings->set("FlameKeyOverride", flameKey); - m_settings->reset("CFKeyOverride"); - } m_settings->registerSetting("FallbackMRBlockedMods", true); m_settings->registerSetting("ModrinthToken", ""); m_settings->registerSetting("UserAgentOverride", ""); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/BaseInstance.cpp new/PrismLauncher-11.1.0/launcher/BaseInstance.cpp --- old/PrismLauncher-11.0.3/launcher/BaseInstance.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/BaseInstance.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -42,6 +42,7 @@ #include <QFileInfo> #include <QJsonDocument> #include <QJsonObject> +#include <QUuid> #include "Application.h" #include "Json.h" @@ -89,6 +90,14 @@ m_settings->registerSetting("linkedInstances", "[]"); m_settings->registerSetting("shortcuts", QString()); + m_settings->registerSetting("uuid", QString()); + + const auto savedUUID = m_settings->get("uuid").toString(); + if (savedUUID.isEmpty()) { + regenerateUuid(); + } else { + m_uuid = savedUUID; + } // Game time override auto gameTimeOverride = m_settings->registerSetting("OverrideGameTime", false); @@ -269,6 +278,13 @@ return QFileInfo(instanceRoot()).fileName(); } +void BaseInstance::regenerateUuid() +{ + const auto newUUID = QUuid::createUuid().toString(QUuid::Id128); + m_settings->set("uuid", newUUID); + m_uuid = newUUID; +} + bool BaseInstance::isRunning() const { return m_isRunning; @@ -446,7 +462,7 @@ QString shortcutName = dict["name"].toString(); QString filePath = dict["filePath"].toString(); - if (!QDir(filePath).exists()) { + if (!QFileInfo::exists(filePath)) { qWarning() << "Shortcut" << shortcutName << "for instance" << name() << "have non-existent path" << filePath; continue; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/BaseInstance.h new/PrismLauncher-11.1.0/launcher/BaseInstance.h --- old/PrismLauncher-11.0.3/launcher/BaseInstance.h 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/BaseInstance.h 2026-09-03 08:14:38.000000000 +0200 @@ -114,7 +114,9 @@ /// The instance's ID. The ID SHALL be determined by LAUNCHER internally. The ID IS guaranteed to /// be unique. - virtual QString id() const; + QString id() const; + QString uuid() const { return m_uuid; } + void regenerateUuid(); void setMinecraftRunning(bool running); void setRunning(bool running); @@ -315,6 +317,7 @@ RuntimeContext m_runtimeContext; private: /* data */ + QString m_uuid; Status m_status = Status::Present; bool m_crashed = false; bool m_hasUpdate = false; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/CMakeLists.txt new/PrismLauncher-11.1.0/launcher/CMakeLists.txt --- old/PrismLauncher-11.0.3/launcher/CMakeLists.txt 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/CMakeLists.txt 2026-09-03 08:14:38.000000000 +0200 @@ -1097,6 +1097,8 @@ ui/dialogs/InstallLoaderDialog.h ui/dialogs/ChooseOfflineNameDialog.cpp ui/dialogs/ChooseOfflineNameDialog.h + ui/dialogs/UntrustedModsDialog.cpp + ui/dialogs/UntrustedModsDialog.h ui/dialogs/skins/SkinManageDialog.cpp ui/dialogs/skins/SkinManageDialog.h @@ -1268,6 +1270,7 @@ ui/dialogs/ChooseProviderDialog.ui ui/dialogs/skins/SkinManageDialog.ui ui/dialogs/ChooseOfflineNameDialog.ui + ui/dialogs/UntrustedModsDialog.ui ) qt_wrap_ui(PRISM_UPDATE_UI diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/HardwareInfo.cpp new/PrismLauncher-11.1.0/launcher/HardwareInfo.cpp --- old/PrismLauncher-11.0.3/launcher/HardwareInfo.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/HardwareInfo.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -21,12 +21,14 @@ #include <QDebug> #include <QStringList> -#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX) +#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) namespace { +#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX) QString afterColon(QString str) { return str.remove(0, str.indexOf(':') + 2).trimmed(); } +#endif template <typename F> bool readFromOutput(const char* command, F function) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/InstanceCopyTask.cpp new/PrismLauncher-11.1.0/launcher/InstanceCopyTask.cpp --- old/PrismLauncher-11.0.3/launcher/InstanceCopyTask.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/InstanceCopyTask.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -151,6 +151,7 @@ BaseInstance* inst(new NullInstance(m_globalSettings, std::move(instanceSettings), m_stagingPath)); inst->setName(name()); inst->setIconKey(m_instIcon); + inst->regenerateUuid(); if (!m_keepPlaytime) { inst->resetTimePlayed(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/InstanceDirUpdate.cpp new/PrismLauncher-11.1.0/launcher/InstanceDirUpdate.cpp --- old/PrismLauncher-11.0.3/launcher/InstanceDirUpdate.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/InstanceDirUpdate.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -66,6 +66,13 @@ return QString(); } + if (instance->isRunning()) { + QMessageBox::warning(parent, QObject::tr("Cannot rename instance folder"), + QObject::tr("The instance folder cannot be renamed while the instance is running.\n\n" + "Only the instance name will be changed. The folder will keep its current name.")); + return QString(); + } + // Ask if we should rename if (renamingMode == "AskEverytime") { auto checkBox = new QCheckBox(QObject::tr("&Remember my choice"), parent); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/InstanceImportTask.cpp new/PrismLauncher-11.1.0/launcher/InstanceImportTask.cpp --- old/PrismLauncher-11.0.3/launcher/InstanceImportTask.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/InstanceImportTask.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -59,8 +59,8 @@ #include <QtConcurrentRun> #include <memory> -InstanceImportTask::InstanceImportTask(const QUrl& sourceUrl, QWidget* parent, QMap<QString, QString>&& extra_info) - : m_sourceUrl(sourceUrl), m_extra_info(extra_info), m_parent(parent) +InstanceImportTask::InstanceImportTask(const QUrl& sourceUrl, bool trustedSource, QWidget* parent, QMap<QString, QString>&& extra_info) + : m_sourceUrl(sourceUrl), m_trustedSource(trustedSource), m_extra_info(extra_info), m_parent(parent) {} bool InstanceImportTask::abort() @@ -287,11 +287,12 @@ if (original_instance_id_it != m_extra_info.constEnd()) original_instance_id = original_instance_id_it.value(); - inst_creation_task = - makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); + inst_creation_task = makeShared<FlameCreationTask>(m_stagingPath, m_trustedSource, m_globalSettings, m_parent, pack_id, + pack_version_id, original_instance_id); } else { // FIXME: Find a way to get IDs in directly imported ZIPs - inst_creation_task = makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, QString(), QString()); + inst_creation_task = + makeShared<FlameCreationTask>(m_stagingPath, m_trustedSource, m_globalSettings, m_parent, QString(), QString()); } inst_creation_task->setName(*this); @@ -349,6 +350,9 @@ // reset time played on import... because packs. instance.resetTimePlayed(); + // UUID is carried over on export, but this is a distinct instance, so give it its own + instance.regenerateUuid(); + // set a new nice name instance.setName(name()); @@ -381,8 +385,8 @@ if (original_instance_id_it != m_extra_info.constEnd()) original_instance_id = original_instance_id_it.value(); - inst_creation_task = - makeShared<ModrinthCreationTask>(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); + inst_creation_task = makeShared<ModrinthCreationTask>(m_stagingPath, m_trustedSource, m_globalSettings, m_parent, pack_id, + pack_version_id, original_instance_id); } else { QString pack_id; if (!m_sourceUrl.isEmpty()) { @@ -391,7 +395,7 @@ } // FIXME: Find a way to get the ID in directly imported ZIPs - inst_creation_task = makeShared<ModrinthCreationTask>(m_stagingPath, m_globalSettings, m_parent, pack_id); + inst_creation_task = makeShared<ModrinthCreationTask>(m_stagingPath, m_trustedSource, m_globalSettings, m_parent, pack_id); } inst_creation_task->setName(*this); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/InstanceImportTask.h new/PrismLauncher-11.1.0/launcher/InstanceImportTask.h --- old/PrismLauncher-11.0.3/launcher/InstanceImportTask.h 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/InstanceImportTask.h 2026-09-03 08:14:38.000000000 +0200 @@ -43,7 +43,10 @@ class InstanceImportTask : public InstanceTask { Q_OBJECT public: - explicit InstanceImportTask(const QUrl& sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {}); + explicit InstanceImportTask(const QUrl& sourceUrl, + bool trustedSource, + QWidget* parent = nullptr, + QMap<QString, QString>&& extra_info = {}); virtual ~InstanceImportTask() = default; bool abort() override; @@ -63,6 +66,7 @@ private: /* data */ QUrl m_sourceUrl; + bool m_trustedSource; QString m_archivePath; Task::Ptr m_task; enum class ModpackType { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/InstanceList.cpp new/PrismLauncher-11.1.0/launcher/InstanceList.cpp --- old/PrismLauncher-11.0.3/launcher/InstanceList.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/InstanceList.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -612,7 +612,7 @@ if (instId.isEmpty()) return nullptr; for (auto& inst : m_instances) { - if (inst->id() == instId) { + if (inst->id() == instId || inst->uuid() == instId) { return inst.get(); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/meta/BaseEntity.cpp new/PrismLauncher-11.1.0/launcher/meta/BaseEntity.cpp --- old/PrismLauncher-11.0.3/launcher/meta/BaseEntity.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/meta/BaseEntity.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -143,7 +143,7 @@ } } catch (const Exception& e) { - qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause()); + qCritical() << 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; @@ -177,10 +177,10 @@ m_task->addNetAction(dl); m_task->setAskRetry(false); connect(m_task.get(), &Task::failed, this, &BaseEntityLoadTask::emitFailed); - connect(m_task.get(), &Task::succeeded, this, &BaseEntityLoadTask::emitSucceeded); connect(m_task.get(), &Task::succeeded, this, [this]() { m_entity->m_load_status = BaseEntity::LoadStatus::Remote; m_entity->m_file_sha256 = m_entity->m_sha256; + emitSucceeded(); }); connect(m_task.get(), &Task::progress, this, &Task::setProgress); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/minecraft/MinecraftInstance.cpp new/PrismLauncher-11.1.0/launcher/minecraft/MinecraftInstance.cpp --- old/PrismLauncher-11.0.3/launcher/minecraft/MinecraftInstance.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/minecraft/MinecraftInstance.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -238,7 +238,9 @@ auto envSetting = m_settings->registerSetting("OverrideEnv", false); m_settings->registerOverride(global_settings->getSetting("Env"), envSetting); - m_settings->set("InstanceType", "OneSix"); + if (m_settings->get("InstanceType").toString() != "OneSix") { + m_settings->set("InstanceType", "OneSix"); + } } // Join server on launch, this does not have a global override diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/minecraft/ShortcutUtils.cpp new/PrismLauncher-11.1.0/launcher/minecraft/ShortcutUtils.cpp --- old/PrismLauncher-11.0.3/launcher/minecraft/ShortcutUtils.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/minecraft/ShortcutUtils.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -146,7 +146,7 @@ QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Not supported on your platform!")); return false; #endif - args.append({ "--launch", shortcut.instance->id() }); + args.append({ "--launch", shortcut.instance->uuid() }); args.append(shortcut.extraArgs); QString shortcutPath = FS::createShortcut(filePath, appPath, args, shortcut.name, iconPath); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/minecraft/mod/Resource.cpp new/PrismLauncher-11.1.0/launcher/minecraft/mod/Resource.cpp --- old/PrismLauncher-11.0.3/launcher/minecraft/mod/Resource.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/minecraft/mod/Resource.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -46,6 +46,7 @@ m_internal_id = file_name; std::tie(m_size_str, m_size_info) = calculateFileSize(m_file_info); + m_hardLinkCount = FS::hardLinkCount(m_file_info.absoluteFilePath()); if (m_file_info.isDir()) { m_type = ResourceType::FOLDER; m_name = file_name; @@ -287,7 +288,7 @@ bool Resource::isMoreThanOneHardLink() const { - return FS::hardLinkCount(m_file_info.absoluteFilePath()) > 1; + return m_hardLinkCount > 1; } auto Resource::getOriginalFileName() const -> QString diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/minecraft/mod/Resource.h new/PrismLauncher-11.1.0/launcher/minecraft/mod/Resource.h --- old/PrismLauncher-11.0.3/launcher/minecraft/mod/Resource.h 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/minecraft/mod/Resource.h 2026-09-03 08:14:38.000000000 +0200 @@ -35,6 +35,8 @@ #pragma once +#include <cstdint> + #include <QDateTime> #include <QFileInfo> #include <QObject> @@ -210,4 +212,5 @@ int m_resolution_ticket = 0; QString m_size_str; qint64 m_size_info; + std::uintmax_t m_hardLinkCount = 0; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp new/PrismLauncher-11.1.0/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp --- old/PrismLauncher-11.0.3/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -37,7 +37,7 @@ static ModPlatform::ModLoaderTypes mcLoaders(BaseInstance* inst) { - return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getSupportedModLoaders().value(); + return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getSupportedModLoaders().value_or(ModPlatform::ModLoaderTypes(0)); } static bool checkDependencies(std::shared_ptr<GetModDependenciesTask::PackDependency> sel, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/modplatform/flame/FlameInstanceCreationTask.cpp new/PrismLauncher-11.1.0/launcher/modplatform/flame/FlameInstanceCreationTask.cpp --- old/PrismLauncher-11.0.3/launcher/modplatform/flame/FlameInstanceCreationTask.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/modplatform/flame/FlameInstanceCreationTask.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -68,6 +68,7 @@ #include "minecraft/World.h" #include "minecraft/mod/tasks/LocalResourceParse.h" #include "net/ApiDownload.h" +#include "ui/dialogs/UntrustedModsDialog.h" #include "ui/pages/modplatform/OptionalModDialog.h" static const FlameAPI api; @@ -307,6 +308,31 @@ return loaderVersion; } +bool FlameCreationTask::promptForUntrustedMods() +{ + if (m_trustedSource) { + return true; + } + + QStringList untrustedMods; + + const QDir mcDir{ FS::PathCombine(m_stagingPath, "minecraft") }; + const QString modsPath{ FS::PathCombine(m_stagingPath, "minecraft/mods") }; + if (QDir(modsPath).exists()) { + QDirIterator iter{ modsPath, QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks }; + while (iter.hasNext()) { + untrustedMods.append(mcDir.relativeFilePath(iter.next())); + } + } + + if (untrustedMods.empty()) { + return true; + } + + UntrustedModsDialog dialog{ untrustedMods, m_parent }; + return dialog.exec() == QDialog::Accepted; +} + std::unique_ptr<MinecraftInstance> FlameCreationTask::createInstance() { QEventLoop loop; @@ -345,6 +371,12 @@ } } + if (!promptForUntrustedMods()) { + m_abort = true; + emitAborted(); + return nullptr; + } + QString loaderType; QString loaderUid; QString loaderVersion; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/modplatform/flame/FlameInstanceCreationTask.h new/PrismLauncher-11.1.0/launcher/modplatform/flame/FlameInstanceCreationTask.h --- old/PrismLauncher-11.0.3/launcher/modplatform/flame/FlameInstanceCreationTask.h 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/modplatform/flame/FlameInstanceCreationTask.h 2026-09-03 08:14:38.000000000 +0200 @@ -52,12 +52,13 @@ public: FlameCreationTask(const QString& staging_path, + bool trustedSource, SettingsObject* global_settings, QWidget* parent, QString id, QString version_id, QString original_instance_id = {}) - : InstanceCreationTask(), m_parent(parent), m_managedId(std::move(id)), m_managedVersionId(std::move(version_id)) + : InstanceCreationTask(), m_parent(parent), m_trustedSource(trustedSource), m_managedId(std::move(id)), m_managedVersionId(std::move(version_id)) { setStagingPath(staging_path); setParentSettings(global_settings); @@ -77,8 +78,11 @@ void validateOtherResources(QEventLoop& loop); QString getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion); + [[nodiscard]] bool promptForUntrustedMods(); + private: QWidget* m_parent = nullptr; + bool m_trustedSource; shared_qobject_ptr<Flame::FileResolvingTask> m_modIdResolver; Flame::Manifest m_pack; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp new/PrismLauncher-11.1.0/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp --- old/PrismLauncher-11.0.3/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -23,6 +23,7 @@ #include "settings/INISettingsObject.h" #include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/UntrustedModsDialog.h" #include "ui/pages/modplatform/OptionalModDialog.h" #include <QAbstractButton> @@ -205,6 +206,12 @@ } } + if (!promptForUntrustedMods()) { + m_abort = true; + emitAborted(); + return nullptr; + } + QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg"); auto instanceSettings = std::make_unique<INISettingsObject>(configPath); auto instance = std::make_unique<MinecraftInstance>(m_globalSettings, std::move(instanceSettings), m_stagingPath); @@ -495,3 +502,37 @@ return true; } + +bool ModrinthCreationTask::promptForUntrustedMods() +{ + if (m_trustedSource) { + return true; + } + + QStringList untrustedMods; + + for (const auto& file : m_files) { + for (const auto& url : file.downloads) { + if (url.scheme() != "https" || url.host() != BuildConfig.MODRINTH_DOWNLOAD_HOST) { + untrustedMods.append(file.path); + break; + } + } + } + + const QDir mcDir{ FS::PathCombine(m_stagingPath, m_root_path) }; + const QString modsPath{ FS::PathCombine(m_stagingPath, m_root_path, "mods") }; + if (QDir(modsPath).exists()) { + QDirIterator iter{ modsPath, QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks }; + while (iter.hasNext()) { + untrustedMods.append(mcDir.relativeFilePath(iter.next())); + } + } + + if (untrustedMods.empty()) { + return true; + } + + UntrustedModsDialog dialog{ untrustedMods, m_parent }; + return dialog.exec() == QDialog::Accepted; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h new/PrismLauncher-11.1.0/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h --- old/PrismLauncher-11.0.3/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h 2026-09-03 08:14:38.000000000 +0200 @@ -25,12 +25,13 @@ public: ModrinthCreationTask(const QString& stagingPath, + bool trustedSource, SettingsObject* globalSettings, QWidget* parent, QString id, QString versionId = {}, QString originalInstanceId = {}) - : m_parent(parent), m_managed_id(std::move(id)), m_managed_version_id(std::move(versionId)) + : m_parent(parent), m_trustedSource(trustedSource), m_managed_id(std::move(id)), m_managed_version_id(std::move(versionId)) { setStagingPath(stagingPath); setParentSettings(globalSettings); @@ -46,8 +47,11 @@ private: bool parseManifest(const QString&, std::vector<File>&, bool setInternalData = true, bool showOptionalDialog = true); + [[nodiscard]] bool promptForUntrustedMods(); + private: QWidget* m_parent = nullptr; + bool m_trustedSource; QString m_minecraft_version, m_fabric_version, m_quilt_version, m_forge_version, m_neoForge_version; QString m_managed_id, m_managed_version_id, m_managed_name; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/settings/INISettingsObject.cpp new/PrismLauncher-11.1.0/launcher/settings/INISettingsObject.cpp --- old/PrismLauncher-11.0.3/launcher/settings/INISettingsObject.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/settings/INISettingsObject.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -51,19 +51,33 @@ bool INISettingsObject::reload() { - return m_ini.loadFile(m_filePath) && SettingsObject::reload(); + if (!m_ini.loadFile(m_filePath)) { + return false; + } + + bool suspendSavePrev = m_suspendSave; + bool doSavePrev = m_doSave; + + m_suspendSave = true; + bool result = SettingsObject::reload(); + + m_suspendSave = suspendSavePrev; + m_doSave = doSavePrev; + return result; } void INISettingsObject::suspendSave() { + Q_ASSERT(!m_suspendSave); m_suspendSave = true; } void INISettingsObject::resumeSave() { + Q_ASSERT(m_suspendSave); m_suspendSave = false; if (m_doSave) { - m_ini.saveFile(m_filePath); + doSave(); } } @@ -91,6 +105,7 @@ if (m_suspendSave) { m_doSave = true; } else { + qDebug() << "Saving INI settings to" << m_filePath; m_ini.saveFile(m_filePath); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/settings/Setting.cpp new/PrismLauncher-11.1.0/launcher/settings/Setting.cpp --- old/PrismLauncher-11.0.3/launcher/settings/Setting.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/settings/Setting.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -38,7 +38,9 @@ void Setting::set(QVariant value) { - emit SettingChanged(*this, value); + if (const auto currentValue = get(); value != currentValue) { + emit SettingChanged(*this, value); + } } void Setting::reset() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/dialogs/InstallLoaderDialog.cpp new/PrismLauncher-11.1.0/launcher/ui/dialogs/InstallLoaderDialog.cpp --- old/PrismLauncher-11.0.3/launcher/ui/dialogs/InstallLoaderDialog.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/dialogs/InstallLoaderDialog.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -163,6 +163,9 @@ auto* page = pageCast(container->selectedPage()); if (page->selectedVersion()) { profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); + if (auto component = profile->getComponent(page->id())) { + component->setEnabled(true); + } profile->resolve(Net::Mode::Online); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/dialogs/ResourceDownloadDialog.cpp new/PrismLauncher-11.1.0/launcher/ui/dialogs/ResourceDownloadDialog.cpp --- old/PrismLauncher-11.0.3/launcher/ui/dialogs/ResourceDownloadDialog.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/dialogs/ResourceDownloadDialog.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -305,7 +305,7 @@ { QList<BasePage*> pages; - auto loaders = static_cast<MinecraftInstance*>(m_instance)->getPackProfile()->getSupportedModLoaders().value(); + auto loaders = static_cast<MinecraftInstance*>(m_instance)->getPackProfile()->getSupportedModLoaders().value_or(ModPlatform::ModLoaderTypes(0)); if (ModrinthAPI::validateModLoaders(loaders)) { auto* page = ModrinthModPage::create(this, *m_instance); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/dialogs/UntrustedModsDialog.cpp new/PrismLauncher-11.1.0/launcher/ui/dialogs/UntrustedModsDialog.cpp --- old/PrismLauncher-11.0.3/launcher/ui/dialogs/UntrustedModsDialog.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/PrismLauncher-11.1.0/launcher/ui/dialogs/UntrustedModsDialog.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -0,0 +1,26 @@ +#include "UntrustedModsDialog.h" +#include "ui_UntrustedModsDialog.h" + +#include <QAbstractButton> +#include <QDialogButtonBox> +#include <QPushButton> +#include <QTimer> + +UntrustedModsDialog::UntrustedModsDialog(const QStringList& paths, QWidget* parent) : QDialog{ parent }, m_ui{ new Ui::UntrustedModsDialog } +{ + m_ui->setupUi(this); + m_ui->modList->addItems(paths); + + auto* ok = m_ui->buttonBox->button(QDialogButtonBox::Ok); + ok->setEnabled(false); + + connect(m_ui->confirmCheckbox, &QAbstractButton::clicked, ok, &QWidget::setEnabled); + + m_ui->confirmCheckbox->setEnabled(false); + QTimer::singleShot(3000, this, [this] { m_ui->confirmCheckbox->setEnabled(true); }); +} + +UntrustedModsDialog::~UntrustedModsDialog() +{ + delete m_ui; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/dialogs/UntrustedModsDialog.h new/PrismLauncher-11.1.0/launcher/ui/dialogs/UntrustedModsDialog.h --- old/PrismLauncher-11.0.3/launcher/ui/dialogs/UntrustedModsDialog.h 1970-01-01 01:00:00.000000000 +0100 +++ new/PrismLauncher-11.1.0/launcher/ui/dialogs/UntrustedModsDialog.h 2026-09-03 08:14:38.000000000 +0200 @@ -0,0 +1,20 @@ +#pragma once + +#include <QDialog> +#include <QObject> +#include <QStringList> +#include <QWidget> + +namespace Ui { +class UntrustedModsDialog; +} + +class UntrustedModsDialog : public QDialog { + Q_OBJECT + public: + explicit UntrustedModsDialog(const QStringList& paths, QWidget* parent = nullptr); + ~UntrustedModsDialog() override; + + private: + Ui::UntrustedModsDialog* m_ui; +}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/dialogs/UntrustedModsDialog.ui new/PrismLauncher-11.1.0/launcher/ui/dialogs/UntrustedModsDialog.ui --- old/PrismLauncher-11.0.3/launcher/ui/dialogs/UntrustedModsDialog.ui 1970-01-01 01:00:00.000000000 +0100 +++ new/PrismLauncher-11.1.0/launcher/ui/dialogs/UntrustedModsDialog.ui 2026-09-03 08:14:38.000000000 +0200 @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UntrustedModsDialog</class> + <widget class="QDialog" name="UntrustedModsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>635</width> + <height>269</height> + </rect> + </property> + <property name="windowTitle"> + <string>Easy There!</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="labelAbove"> + <property name="text"> + <string><html><head/><body><p>The modpack you are installing includes mods which are not hosted on Modrinth or CurseForge:</p></body></html></string> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="modList"/> + </item> + <item> + <widget class="QLabel" name="labelBelow"> + <property name="text"> + <string><html><head/><body><p><b>Malicious mods are often distributed through links sent on platforms such as Discord.</b></p><p>We strongly recommend only importing modpacks from trusted sources.</p></body></html></string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="confirmCheckbox"> + <property name="text"> + <string>I trust this modpack and wish to proceed regardless</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>UntrustedModsDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>UntrustedModsDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/pages/instance/InstanceSettingsPage.h new/PrismLauncher-11.1.0/launcher/ui/pages/instance/InstanceSettingsPage.h --- old/PrismLauncher-11.0.3/launcher/ui/pages/instance/InstanceSettingsPage.h 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/pages/instance/InstanceSettingsPage.h 2026-09-03 08:14:38.000000000 +0200 @@ -46,7 +46,7 @@ public: explicit InstanceSettingsPage(MinecraftInstance* instance, QWidget* parent = nullptr) : MinecraftSettingsWidget(instance, parent) { - connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::saveSettings); + connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::apply); connect(APPLICATION, &Application::globalSettingsApplied, this, &InstanceSettingsPage::loadSettings); } ~InstanceSettingsPage() override {} @@ -55,6 +55,7 @@ QString id() const override { return "settings"; } bool apply() override { + SettingsObject::Lock lock(m_instance->settings()); saveSettings(); return true; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/pages/instance/ManagedPackPage.cpp new/PrismLauncher-11.1.0/launcher/ui/pages/instance/ManagedPackPage.cpp --- old/PrismLauncher-11.0.3/launcher/ui/pages/instance/ManagedPackPage.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/pages/instance/ManagedPackPage.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -359,7 +359,7 @@ { auto customURL = m_inst->settings()->get("ManagedPackURL").toString().trimmed(); if (m_inst->getManagedPackID().isEmpty() && !customURL.isEmpty()) { - updatePack(customURL); + updatePack(customURL, false); return; } auto index = ui->versionsComboBox->currentIndex(); @@ -369,7 +369,7 @@ } auto version = m_pack.versions.at(index); - updatePack(version.downloadUrl, version.fileId.toString(), version.version); + updatePack(version.downloadUrl, true, version.fileId.toString(), version.version); } void ModrinthManagedPackPage::updateFromFile() @@ -378,7 +378,7 @@ if (output.isEmpty()) return; - updatePack(output); + updatePack(output, false); } // FLAME @@ -488,7 +488,7 @@ { auto customURL = m_inst->settings()->get("ManagedPackURL").toString().trimmed(); if (m_inst->getManagedPackID().isEmpty() && !customURL.isEmpty()) { - updatePack(customURL); + updatePack(customURL, false); return; } auto index = ui->versionsComboBox->currentIndex(); @@ -498,7 +498,7 @@ } auto version = m_pack.versions.at(index); - updatePack(version.downloadUrl, version.fileId.toString()); + updatePack(version.downloadUrl, true, version.fileId.toString()); } void FlameManagedPackPage::updateFromFile() @@ -507,10 +507,10 @@ if (output.isEmpty()) return; - updatePack(output); + updatePack(output, false); } -void ManagedPackPage::updatePack(const QUrl& url, QString versionID, QString versionName) +void ManagedPackPage::updatePack(const QUrl& url, bool trusted, QString versionID, QString versionName) { QMap<QString, QString> extra_info; // NOTE: Don't use 'm_pack.id' here, since we didn't completely parse all the metadata for the pack, including this field. @@ -518,7 +518,7 @@ extra_info.insert("pack_version_id", versionID); extra_info.insert("original_instance_id", m_inst->id()); - auto extracted = new InstanceImportTask(url, this, std::move(extra_info)); + auto extracted = new InstanceImportTask(url, trusted, this, std::move(extra_info)); if (versionName.isEmpty()) { extracted->setName(m_inst->name()); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/pages/instance/ManagedPackPage.h new/PrismLauncher-11.1.0/launcher/ui/pages/instance/ManagedPackPage.h --- old/PrismLauncher-11.0.3/launcher/ui/pages/instance/ManagedPackPage.h 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/pages/instance/ManagedPackPage.h 2026-09-03 08:14:38.000000000 +0200 @@ -86,7 +86,7 @@ */ bool runUpdateTask(InstanceTask*); - void updatePack(const QUrl& url, QString versionID = {}, QString versionName = {}); + void updatePack(const QUrl& url, bool trusted, QString versionID = {}, QString versionName = {}); protected: InstanceWindow* m_instance_window = nullptr; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/pages/instance/ModFolderPage.cpp new/PrismLauncher-11.1.0/launcher/ui/pages/instance/ModFolderPage.cpp --- old/PrismLauncher-11.0.3/launcher/ui/pages/instance/ModFolderPage.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/pages/instance/ModFolderPage.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -167,10 +167,8 @@ } auto* profile = static_cast<MinecraftInstance*>(m_instance)->getPackProfile(); - if (!profile->getModLoaders().has_value()) { - if (handleNoModLoader()) { - return; - } + if (!profile->getModLoaders().has_value() && handleNoModLoader()) { + return; } m_downloadDialog = new ResourceDownload::ModDownloadDialog(this, m_model, m_instance); @@ -227,10 +225,8 @@ } auto* profile = static_cast<MinecraftInstance*>(m_instance)->getPackProfile(); - if (!profile->getModLoaders().has_value()) { - if (handleNoModLoader()) { - return; - } + if (!profile->getModLoaders().has_value() && handleNoModLoader()) { + return; } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Mod updates are unavailable when metadata is disabled!")); @@ -337,10 +333,8 @@ } auto* profile = static_cast<MinecraftInstance*>(m_instance)->getPackProfile(); - if (!profile->getModLoaders().has_value()) { - if (handleNoModLoader()) { - return; - } + if (!profile->getModLoaders().has_value() && handleNoModLoader()) { + return; } if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { QMessageBox::critical(this, tr("Error"), tr("Mod updates are unavailable when metadata is disabled!")); @@ -434,12 +428,21 @@ // Should be safe auto* profile = static_cast<MinecraftInstance*>(this->m_instance)->getPackProfile(); InstallLoaderDialog dialog(profile, QString(), this); - bool ret = dialog.exec() != 0; + // true if the user went through the install loader dialog + // false if the dialog got canceled/closed + bool dialogAccepted = dialog.exec() != 0; this->m_container->refreshContainer(); - // returning negation of dialog.exec which'll be true if the install loader dialog got canceled/closed - // and false if the user went through and installed a loader - return !ret; + if (!dialogAccepted) { + return true; + } + if (!profile->getModLoaders().has_value()) { + CustomMessageBox::selectable( + this, tr("Error"), tr("No mod loader was installed. Please try again."), QMessageBox::Warning) + ->show(); + return true; + } + return false; } // Nothing happens the dialog is already closing // returning true so the caller doesn't go and continue with opening it's dialog without a mod loader diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/pages/modplatform/ImportPage.cpp new/PrismLauncher-11.1.0/launcher/ui/pages/modplatform/ImportPage.cpp --- old/PrismLauncher-11.0.3/launcher/ui/pages/modplatform/ImportPage.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/pages/modplatform/ImportPage.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -118,7 +118,7 @@ if (fi.exists() && (isZip || isMRPack)) { auto extra_info = QMap(m_extra_info); qDebug() << "Pack Extra Info" << extra_info << m_extra_info; - dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this, std::move(extra_info))); + dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, false, this, std::move(extra_info))); dialog->setSuggestedIcon("default"); } } else if (url.scheme() == "curseforge") { @@ -163,7 +163,7 @@ extra_info.insert("pack_id", addonId); extra_info.insert("pack_version_id", fileId); - dialog->setSuggestedPack(pack_name, new InstanceImportTask(dl_url, this, std::move(extra_info))); + dialog->setSuggestedPack(pack_name, new InstanceImportTask(dl_url, false, this, std::move(extra_info))); dialog->setSuggestedIcon("default"); } else { @@ -183,7 +183,7 @@ // hook, line and sinker. QFileInfo fi(url.fileName()); auto extra_info = QMap(m_extra_info); - dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this, std::move(extra_info))); + dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, false, this, std::move(extra_info))); dialog->setSuggestedIcon("default"); } } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/pages/modplatform/flame/FlamePage.cpp new/PrismLauncher-11.1.0/launcher/ui/pages/modplatform/flame/FlamePage.cpp --- old/PrismLauncher-11.0.3/launcher/ui/pages/modplatform/flame/FlamePage.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/pages/modplatform/flame/FlamePage.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -241,7 +241,7 @@ extra_info.insert("pack_id", m_current->addonId.toString()); extra_info.insert("pack_version_id", version.fileId.toString()); - m_dialog->setSuggestedPack(m_current->name, new InstanceImportTask(version.downloadUrl, this, std::move(extra_info))); + m_dialog->setSuggestedPack(m_current->name, new InstanceImportTask(version.downloadUrl, true, this, std::move(extra_info))); QString editedLogoName = "curseforge_" + m_current->logoName; m_listModel->getLogo(m_current->logoName, m_current->logoUrl, [this, editedLogoName](QString logo) { m_dialog->setSuggestedIconFromFile(logo, editedLogoName); }); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp new/PrismLauncher-11.1.0/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp --- old/PrismLauncher-11.0.3/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -318,7 +318,8 @@ extra_info.insert("pack_id", m_current->addonId.toString()); extra_info.insert("pack_version_id", ver.fileId.toString()); - m_dialog->setSuggestedPack(m_current->name, ver.version, new InstanceImportTask(ver.downloadUrl, this, std::move(extra_info))); + m_dialog->setSuggestedPack(m_current->name, ver.version, + new InstanceImportTask(ver.downloadUrl, true, this, std::move(extra_info))); QString editedLogoName = "modrinth_" + m_current->logoName; m_model->getLogo(m_current->logoName, m_current->logoUrl, [this, editedLogoName](QString logo) { m_dialog->setSuggestedIconFromFile(logo, editedLogoName); }); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/themes/ThemeManager.mm new/PrismLauncher-11.1.0/launcher/ui/themes/ThemeManager.mm --- old/PrismLauncher-11.0.3/launcher/ui/themes/ThemeManager.mm 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/themes/ThemeManager.mm 2026-09-03 08:14:38.000000000 +0200 @@ -31,15 +31,6 @@ window.titlebarAppearsTransparent = YES; window.backgroundColor = [NSColor colorWithRed:color.redF() green:color.greenF() blue:color.blueF() alpha:color.alphaF()]; - // Unfortunately there seems to be no easy way to set the titlebar text color. - // The closest we can do without dubious hacks is set the dark/light mode state based on the brightness of the - // background color, which should at least make the text readable even if we can't use the theme's text color. - // It's a good idea to set this anyway since it also affects some other UI elements like text shadows (PrismLauncher#3825). - if (color.lightnessF() < 0.5) { - window.appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; - } else { - window.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua]; - } } void ThemeManager::setTitlebarColorOfAllWindowsOnMac(QColor color) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/widgets/JavaSettingsWidget.cpp new/PrismLauncher-11.1.0/launcher/ui/widgets/JavaSettingsWidget.cpp --- old/PrismLauncher-11.0.3/launcher/ui/widgets/JavaSettingsWidget.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/widgets/JavaSettingsWidget.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -167,8 +167,6 @@ else settings = APPLICATION->settings(); - SettingsObject::Lock lock(settings); - // Java Install Settings bool javaInstall = m_instance == nullptr || m_ui->javaInstallationGroupBox->isChecked(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/widgets/JavaSettingsWidget.ui new/PrismLauncher-11.1.0/launcher/ui/widgets/JavaSettingsWidget.ui --- old/PrismLauncher-11.0.3/launcher/ui/widgets/JavaSettingsWidget.ui 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/widgets/JavaSettingsWidget.ui 2026-09-03 08:14:38.000000000 +0200 @@ -345,7 +345,7 @@ <item> <widget class="QCheckBox" name="lowMemWarningCheckBox"> <property name="text"> - <string>Warn when there is not enough memory available</string> + <string>Warn when there is not enough free memory</string> </property> </widget> </item> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/widgets/MinecraftSettingsWidget.cpp new/PrismLauncher-11.1.0/launcher/ui/widgets/MinecraftSettingsWidget.cpp --- old/PrismLauncher-11.0.3/launcher/ui/widgets/MinecraftSettingsWidget.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/widgets/MinecraftSettingsWidget.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -315,172 +315,168 @@ else settings = APPLICATION->settings(); - { - SettingsObject::Lock lock(settings); + // Console + bool console = m_instance == nullptr || m_ui->consoleSettingsBox->isChecked(); - // Console - bool console = m_instance == nullptr || m_ui->consoleSettingsBox->isChecked(); + if (m_instance != nullptr) + settings->set("OverrideConsole", console); - if (m_instance != nullptr) - settings->set("OverrideConsole", console); + if (console) { + settings->set("ShowConsole", m_ui->showConsoleCheck->isChecked()); + settings->set("AutoCloseConsole", m_ui->autoCloseConsoleCheck->isChecked()); + settings->set("ShowConsoleOnError", m_ui->showConsoleErrorCheck->isChecked()); + } else { + settings->reset("ShowConsole"); + settings->reset("AutoCloseConsole"); + settings->reset("ShowConsoleOnError"); + } - if (console) { - settings->set("ShowConsole", m_ui->showConsoleCheck->isChecked()); - settings->set("AutoCloseConsole", m_ui->autoCloseConsoleCheck->isChecked()); - settings->set("ShowConsoleOnError", m_ui->showConsoleErrorCheck->isChecked()); - } else { - settings->reset("ShowConsole"); - settings->reset("AutoCloseConsole"); - settings->reset("ShowConsoleOnError"); - } + // Game Window + bool window = m_instance == nullptr || m_ui->windowSizeGroupBox->isChecked(); - // Game Window - bool window = m_instance == nullptr || m_ui->windowSizeGroupBox->isChecked(); + if (m_instance != nullptr) { + settings->set("OverrideWindow", window); + settings->set("OverrideMiscellaneous", window); + } - if (m_instance != nullptr) { - settings->set("OverrideWindow", window); - settings->set("OverrideMiscellaneous", window); - } + if (window) { + settings->set("LaunchMaximized", m_ui->maximizedCheckBox->isChecked()); + settings->set("MinecraftWinWidth", m_ui->windowWidthSpinBox->value()); + settings->set("MinecraftWinHeight", m_ui->windowHeightSpinBox->value()); + settings->set("CloseAfterLaunch", m_ui->closeAfterLaunchCheck->isChecked()); + settings->set("QuitAfterGameStop", m_ui->quitAfterGameStopCheck->isChecked()); + } else { + settings->reset("LaunchMaximized"); + settings->reset("MinecraftWinWidth"); + settings->reset("MinecraftWinHeight"); + settings->reset("CloseAfterLaunch"); + settings->reset("QuitAfterGameStop"); + } - if (window) { - settings->set("LaunchMaximized", m_ui->maximizedCheckBox->isChecked()); - settings->set("MinecraftWinWidth", m_ui->windowWidthSpinBox->value()); - settings->set("MinecraftWinHeight", m_ui->windowHeightSpinBox->value()); - settings->set("CloseAfterLaunch", m_ui->closeAfterLaunchCheck->isChecked()); - settings->set("QuitAfterGameStop", m_ui->quitAfterGameStopCheck->isChecked()); - } else { - settings->reset("LaunchMaximized"); - settings->reset("MinecraftWinWidth"); - settings->reset("MinecraftWinHeight"); - settings->reset("CloseAfterLaunch"); - settings->reset("QuitAfterGameStop"); - } + // Custom Commands + bool custcmd = m_instance == nullptr || m_ui->customCommands->checked(); - // Custom Commands - bool custcmd = m_instance == nullptr || m_ui->customCommands->checked(); + if (m_instance != nullptr) + settings->set("OverrideCommands", custcmd); - if (m_instance != nullptr) - settings->set("OverrideCommands", custcmd); + if (custcmd) { + settings->set("PreLaunchCommand", m_ui->customCommands->prelaunchCommand()); + settings->set("WrapperCommand", m_ui->customCommands->wrapperCommand()); + settings->set("PostExitCommand", m_ui->customCommands->postexitCommand()); + } else { + settings->reset("PreLaunchCommand"); + settings->reset("WrapperCommand"); + settings->reset("PostExitCommand"); + } - if (custcmd) { - settings->set("PreLaunchCommand", m_ui->customCommands->prelaunchCommand()); - settings->set("WrapperCommand", m_ui->customCommands->wrapperCommand()); - settings->set("PostExitCommand", m_ui->customCommands->postexitCommand()); - } else { - settings->reset("PreLaunchCommand"); - settings->reset("WrapperCommand"); - settings->reset("PostExitCommand"); - } + // Environment Variables + auto env = m_instance == nullptr || m_ui->environmentVariables->override(); - // Environment Variables - auto env = m_instance == nullptr || m_ui->environmentVariables->override(); + if (m_instance != nullptr) + settings->set("OverrideEnv", env); - if (m_instance != nullptr) - settings->set("OverrideEnv", env); + if (env) + settings->set("Env", Json::fromMap(m_ui->environmentVariables->value())); + else + settings->reset("Env"); - if (env) - settings->set("Env", Json::fromMap(m_ui->environmentVariables->value())); - else - settings->reset("Env"); - - // Workarounds - bool workarounds = m_instance == nullptr || m_ui->nativeWorkaroundsGroupBox->isChecked(); - - if (m_instance != nullptr) - settings->set("OverrideNativeWorkarounds", workarounds); - - if (workarounds) { - settings->set("UseNativeGLFW", m_ui->useNativeGLFWCheck->isChecked()); - settings->set("CustomGLFWPath", m_ui->lineEditGLFWPath->text()); - settings->set("UseNativeOpenAL", m_ui->useNativeOpenALCheck->isChecked()); - settings->set("CustomOpenALPath", m_ui->lineEditOpenALPath->text()); - } else { - settings->reset("UseNativeGLFW"); - settings->reset("CustomGLFWPath"); - settings->reset("UseNativeOpenAL"); - settings->reset("CustomOpenALPath"); - } + // Workarounds + bool workarounds = m_instance == nullptr || m_ui->nativeWorkaroundsGroupBox->isChecked(); - // Performance - bool performance = m_instance == nullptr || m_ui->perfomanceGroupBox->isChecked(); + if (m_instance != nullptr) + settings->set("OverrideNativeWorkarounds", workarounds); - if (m_instance != nullptr) - settings->set("OverridePerformance", performance); + if (workarounds) { + settings->set("UseNativeGLFW", m_ui->useNativeGLFWCheck->isChecked()); + settings->set("CustomGLFWPath", m_ui->lineEditGLFWPath->text()); + settings->set("UseNativeOpenAL", m_ui->useNativeOpenALCheck->isChecked()); + settings->set("CustomOpenALPath", m_ui->lineEditOpenALPath->text()); + } else { + settings->reset("UseNativeGLFW"); + settings->reset("CustomGLFWPath"); + settings->reset("UseNativeOpenAL"); + settings->reset("CustomOpenALPath"); + } - if (performance) { - settings->set("EnableFeralGamemode", m_ui->enableFeralGamemodeCheck->isChecked()); - settings->set("EnableMangoHud", m_ui->enableMangoHud->isChecked()); - settings->set("UseDiscreteGpu", m_ui->useDiscreteGpuCheck->isChecked()); - settings->set("UseZink", m_ui->useZink->isChecked()); - } else { - settings->reset("EnableFeralGamemode"); - settings->reset("EnableMangoHud"); - settings->reset("UseDiscreteGpu"); - settings->reset("UseZink"); - } + // Performance + bool performance = m_instance == nullptr || m_ui->perfomanceGroupBox->isChecked(); - // Game time - bool gameTime = m_instance == nullptr || m_ui->gameTimeGroupBox->isChecked(); + if (m_instance != nullptr) + settings->set("OverridePerformance", performance); - if (m_instance != nullptr) - settings->set("OverrideGameTime", gameTime); + if (performance) { + settings->set("EnableFeralGamemode", m_ui->enableFeralGamemodeCheck->isChecked()); + settings->set("EnableMangoHud", m_ui->enableMangoHud->isChecked()); + settings->set("UseDiscreteGpu", m_ui->useDiscreteGpuCheck->isChecked()); + settings->set("UseZink", m_ui->useZink->isChecked()); + } else { + settings->reset("EnableFeralGamemode"); + settings->reset("EnableMangoHud"); + settings->reset("UseDiscreteGpu"); + settings->reset("UseZink"); + } - if (gameTime) { - settings->set("ShowGameTime", m_ui->showGameTime->isChecked()); - settings->set("RecordGameTime", m_ui->recordGameTime->isChecked()); - } else { - settings->reset("ShowGameTime"); - settings->reset("RecordGameTime"); - } + // Game time + bool gameTime = m_instance == nullptr || m_ui->gameTimeGroupBox->isChecked(); - if (m_instance == nullptr) { - settings->set("ShowGlobalGameTime", m_ui->showGlobalGameTime->isChecked()); - settings->set("ShowGameTimeWithoutDays", m_ui->showGameTimeWithoutDays->isChecked()); - } + if (m_instance != nullptr) + settings->set("OverrideGameTime", gameTime); - if (m_instance != nullptr) { - // Join server on launch - bool joinServerOnLaunch = m_ui->serverJoinGroupBox->isChecked(); - settings->set("JoinServerOnLaunch", joinServerOnLaunch); - if (joinServerOnLaunch) { - if (m_ui->serverJoinAddressButton->isChecked() || !m_quickPlaySingleplayer) { - settings->set("JoinServerOnLaunchAddress", m_ui->serverJoinAddress->text()); - settings->reset("JoinWorldOnLaunch"); - } else { - settings->set("JoinWorldOnLaunch", m_ui->worldsCb->currentText()); - settings->reset("JoinServerOnLaunchAddress"); - } + if (gameTime) { + settings->set("ShowGameTime", m_ui->showGameTime->isChecked()); + settings->set("RecordGameTime", m_ui->recordGameTime->isChecked()); + } else { + settings->reset("ShowGameTime"); + settings->reset("RecordGameTime"); + } + + if (m_instance == nullptr) { + settings->set("ShowGlobalGameTime", m_ui->showGlobalGameTime->isChecked()); + settings->set("ShowGameTimeWithoutDays", m_ui->showGameTimeWithoutDays->isChecked()); + } + + if (m_instance != nullptr) { + // Join server on launch + bool joinServerOnLaunch = m_ui->serverJoinGroupBox->isChecked(); + settings->set("JoinServerOnLaunch", joinServerOnLaunch); + if (joinServerOnLaunch) { + if (m_ui->serverJoinAddressButton->isChecked() || !m_quickPlaySingleplayer) { + settings->set("JoinServerOnLaunchAddress", m_ui->serverJoinAddress->text()); + settings->reset("JoinWorldOnLaunch"); } else { + settings->set("JoinWorldOnLaunch", m_ui->worldsCb->currentText()); settings->reset("JoinServerOnLaunchAddress"); - settings->reset("JoinWorldOnLaunch"); } + } else { + settings->reset("JoinServerOnLaunchAddress"); + settings->reset("JoinWorldOnLaunch"); + } - // Use an account for this instance - bool useAccountForInstance = m_ui->instanceAccountGroupBox->isChecked(); - settings->set("UseAccountForInstance", useAccountForInstance); - if (useAccountForInstance) { - int accountIndex = m_ui->instanceAccountSelector->currentIndex(); - - if (accountIndex != -1) { - const MinecraftAccountPtr account = APPLICATION->accounts()->at(accountIndex); - if (account != nullptr) - settings->set("InstanceAccountId", account->profileId()); - } - } else { - settings->reset("InstanceAccountId"); + // Use an account for this instance + bool useAccountForInstance = m_ui->instanceAccountGroupBox->isChecked(); + settings->set("UseAccountForInstance", useAccountForInstance); + if (useAccountForInstance) { + int accountIndex = m_ui->instanceAccountSelector->currentIndex(); + + if (accountIndex != -1) { + const MinecraftAccountPtr account = APPLICATION->accounts()->at(accountIndex); + if (account != nullptr) + settings->set("InstanceAccountId", account->profileId()); } + } else { + settings->reset("InstanceAccountId"); } + } - bool overrideLegacySettings = m_instance == nullptr || m_ui->legacySettingsGroupBox->isChecked(); + bool overrideLegacySettings = m_instance == nullptr || m_ui->legacySettingsGroupBox->isChecked(); - if (m_instance != nullptr) - settings->set("OverrideLegacySettings", overrideLegacySettings); + if (m_instance != nullptr) + settings->set("OverrideLegacySettings", overrideLegacySettings); - if (overrideLegacySettings) { - settings->set("OnlineFixes", m_ui->onlineFixes->isChecked()); - } else { - settings->reset("OnlineFixes"); - } + if (overrideLegacySettings) { + settings->set("OnlineFixes", m_ui->onlineFixes->isChecked()); + } else { + settings->reset("OnlineFixes"); } if (m_javaSettings != nullptr) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/widgets/MinecraftSettingsWidget.h new/PrismLauncher-11.1.0/launcher/ui/widgets/MinecraftSettingsWidget.h --- old/PrismLauncher-11.0.3/launcher/ui/widgets/MinecraftSettingsWidget.h 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/widgets/MinecraftSettingsWidget.h 2026-09-03 08:14:38.000000000 +0200 @@ -61,7 +61,10 @@ void saveDataPacksPath(); void selectDataPacksFolder(); + protected: MinecraftInstance* m_instance; + + public: Ui::MinecraftSettingsWidget* m_ui; JavaSettingsWidget* m_javaSettings = nullptr; bool m_quickPlaySingleplayer = false; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PrismLauncher-11.0.3/launcher/ui/widgets/ModFilterWidget.cpp new/PrismLauncher-11.1.0/launcher/ui/widgets/ModFilterWidget.cpp --- old/PrismLauncher-11.0.3/launcher/ui/widgets/ModFilterWidget.cpp 2026-07-11 20:26:38.000000000 +0200 +++ new/PrismLauncher-11.1.0/launcher/ui/widgets/ModFilterWidget.cpp 2026-09-03 08:14:38.000000000 +0200 @@ -234,7 +234,7 @@ loaders |= ModPlatform::getModLoaderFromString(loader); } } else { - loaders = m_instance->getPackProfile()->getSupportedModLoaders().value(); + loaders = m_instance->getPackProfile()->getSupportedModLoaders().value_or(ModPlatform::ModLoaderTypes(0)); } ui->neoForge->setChecked(loaders & ModPlatform::NeoForge); ui->forge->setChecked(loaders & ModPlatform::Forge);
