From aa9896031de51e0378fe14d22f43e00723977c7a Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Mon, 2 Feb 2026 16:03:34 +0500 Subject: [PATCH 1/9] refactor(InstanceCreationTask): return created instance to caller Signed-off-by: Octol1ttle --- launcher/InstanceCreationTask.h | 5 ++- .../minecraft/VanillaInstanceCreationTask.cpp | 14 +++--- .../minecraft/VanillaInstanceCreationTask.h | 2 +- .../flame/FlameInstanceCreationTask.cpp | 38 ++++++++-------- .../flame/FlameInstanceCreationTask.h | 2 +- .../modrinth/ModrinthInstanceCreationTask.cpp | 45 ++++++++++--------- .../modrinth/ModrinthInstanceCreationTask.h | 2 +- 7 files changed, 56 insertions(+), 52 deletions(-) diff --git a/launcher/InstanceCreationTask.h b/launcher/InstanceCreationTask.h index 84fb2a145..95dc816a2 100644 --- a/launcher/InstanceCreationTask.h +++ b/launcher/InstanceCreationTask.h @@ -2,6 +2,7 @@ #include "BaseVersion.h" #include "InstanceTask.h" +#include "minecraft/MinecraftInstance.h" class InstanceCreationTask : public InstanceTask { Q_OBJECT @@ -27,9 +28,9 @@ class InstanceCreationTask : public InstanceTask { /** * Creates a new instance. * - * Returns whether the instance creation was successful (true) or not (false). + * Returns the instance if it was created or nullptr otherwise. */ - virtual bool createInstance() { return false; }; + virtual std::unique_ptr createInstance() { return nullptr; } QString getError() const { return m_error_message; } diff --git a/launcher/minecraft/VanillaInstanceCreationTask.cpp b/launcher/minecraft/VanillaInstanceCreationTask.cpp index 420ffd3c3..017f85027 100644 --- a/launcher/minecraft/VanillaInstanceCreationTask.cpp +++ b/launcher/minecraft/VanillaInstanceCreationTask.cpp @@ -15,22 +15,22 @@ VanillaCreationTask::VanillaCreationTask(BaseVersion::Ptr version, QString loade , m_loader_version(std::move(loader_version)) {} -bool VanillaCreationTask::createInstance() +std::unique_ptr VanillaCreationTask::createInstance() { setStatus(tr("Creating instance from version %1").arg(m_version->name())); - MinecraftInstance inst(m_globalSettings, std::make_unique(FS::PathCombine(m_stagingPath, "instance.cfg")), + auto inst = std::make_unique(m_globalSettings, std::make_unique(FS::PathCombine(m_stagingPath, "instance.cfg")), m_stagingPath); - SettingsObject::Lock lock(inst.settings()); + SettingsObject::Lock lock(inst->settings()); - auto components = inst.getPackProfile(); + auto components = inst->getPackProfile(); components->buildingFromScratch(); components->setComponentVersion("net.minecraft", m_version->descriptor(), true); if (m_using_loader) components->setComponentVersion(m_loader, m_loader_version->descriptor()); - inst.setName(name()); - inst.setIconKey(m_instIcon); + inst->setName(name()); + inst->setIconKey(m_instIcon); - return true; + return inst; } diff --git a/launcher/minecraft/VanillaInstanceCreationTask.h b/launcher/minecraft/VanillaInstanceCreationTask.h index d1b816824..7015a4fe5 100644 --- a/launcher/minecraft/VanillaInstanceCreationTask.h +++ b/launcher/minecraft/VanillaInstanceCreationTask.h @@ -10,7 +10,7 @@ class VanillaCreationTask final : public InstanceCreationTask { VanillaCreationTask(BaseVersion::Ptr version) : InstanceCreationTask(), m_version(std::move(version)) {} VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version); - bool createInstance() override; + std::unique_ptr createInstance() override; private: // Version to update to / create of the instance. diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 2fe9ca2da..98cd6fb28 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -316,7 +316,7 @@ QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, return loaderVersion; } -bool FlameCreationTask::createInstance() +std::unique_ptr FlameCreationTask::createInstance() { QEventLoop loop; @@ -334,7 +334,7 @@ bool FlameCreationTask::createInstance() } catch (const JSONValidationError& e) { setError(tr("Could not understand pack manifest:\n") + e.cause()); - return false; + return nullptr; } if (!m_pack.overrides.isEmpty()) { @@ -346,7 +346,7 @@ bool FlameCreationTask::createInstance() QString mcPath = FS::PathCombine(m_stagingPath, "minecraft"); if (!FS::move(overridePath, mcPath)) { setError(tr("Could not rename the overrides folder:\n") + m_pack.overrides); - return false; + return nullptr; } } else { logWarning( @@ -387,7 +387,7 @@ bool FlameCreationTask::createInstance() QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg"); auto instanceSettings = std::make_unique(configPath); - MinecraftInstance instance(m_globalSettings, std::move(instanceSettings), m_stagingPath); + auto instance = std::make_unique(m_globalSettings, std::move(instanceSettings), m_stagingPath); auto mcVersion = m_pack.minecraft.version; // Hack to correct some 'special sauce'... @@ -397,25 +397,25 @@ bool FlameCreationTask::createInstance() logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack.")); } - auto components = instance.getPackProfile(); + auto components = instance->getPackProfile(); components->buildingFromScratch(); components->setComponentVersion("net.minecraft", mcVersion, true); if (!loaderType.isEmpty()) { auto version = getVersionForLoader(loaderUid, loaderType, loaderVersion, mcVersion); if (version.isEmpty()) - return false; + return nullptr; components->setComponentVersion(loaderUid, version); } if (m_instIcon != "default") { - instance.setIconKey(m_instIcon); + instance->setIconKey(m_instIcon); } else { if (m_pack.name.contains("Direwolf20")) { - instance.setIconKey("steve"); + instance->setIconKey("steve"); } else if (m_pack.name.contains("FTB") || m_pack.name.contains("Feed The Beast")) { - instance.setIconKey("ftb_logo"); + instance->setIconKey("ftb_logo"); } else { - instance.setIconKey("flame"); + instance->setIconKey("flame"); } } @@ -433,8 +433,8 @@ bool FlameCreationTask::createInstance() recommendedRAM = max; } - instance.settings()->set("OverrideMemory", true); - instance.settings()->set("MaxMemAlloc", recommendedRAM); + instance->settings()->set("OverrideMemory", true); + instance->settings()->set("MaxMemAlloc", recommendedRAM); } QString jarmodsPath = FS::PathCombine(m_stagingPath, "minecraft", "jarmods"); @@ -448,7 +448,7 @@ bool FlameCreationTask::createInstance() qDebug() << info.fileName(); jarMods.push_back(info.absoluteFilePath()); } - auto profile = instance.getPackProfile(); + auto profile = instance->getPackProfile(); profile->installJarMods(jarMods); // nuke the original files FS::deletePath(jarmodsPath); @@ -456,11 +456,11 @@ bool FlameCreationTask::createInstance() // Don't add managed info to packs without an ID (most likely imported from ZIP) if (!m_managedId.isEmpty()) - instance.setManagedPack("flame", m_managedId, m_pack.name, m_managedVersionId, m_pack.version); + instance->setManagedPack("flame", m_managedId, m_pack.name, m_managedVersionId, m_pack.version); else - instance.setManagedPack("flame", "", name(), "", ""); + instance->setManagedPack("flame", "", name(), "", ""); - instance.setName(name()); + instance->setName(name()); m_modIdResolver.reset(new Flame::FileResolvingTask(m_pack)); connect(m_modIdResolver.get(), &Flame::FileResolvingTask::succeeded, this, [this, &loop] { idResolverSucceeded(loop); }); @@ -485,10 +485,10 @@ bool FlameCreationTask::createInstance() setAbortable(false); auto inst = m_instance.value(); - inst->copyManagedPack(instance); + inst->copyManagedPack(*instance); } - return did_succeed; + return instance; } void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) @@ -545,7 +545,7 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) BlockedModsDialog message_dialog(m_parent, tr("Blocked mods found"), tr("The following files are not available for download in third party launchers.
" - "You will need to manually download them and add them to the instance."), + "You will need to manually download them and add them to the instance->"), blocked_mods); message_dialog.setModal(true); diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h index 2fe81a909..221ceaf22 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.h +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h @@ -68,7 +68,7 @@ class FlameCreationTask final : public InstanceCreationTask { bool abort() override; bool updateInstance() override; - bool createInstance() override; + std::unique_ptr createInstance() override; private slots: void idResolverSucceeded(QEventLoop&); diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 45ac61273..3bc3dc755 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -169,7 +169,7 @@ bool ModrinthCreationTask::updateInstance() } // https://docs.modrinth.com/docs/modpacks/format_definition/ -bool ModrinthCreationTask::createInstance() +std::unique_ptr ModrinthCreationTask::createInstance() { QEventLoop loop; @@ -177,7 +177,7 @@ bool ModrinthCreationTask::createInstance() QString index_path = FS::PathCombine(m_stagingPath, "modrinth.index.json"); if (m_files.empty() && !parseManifest(index_path, m_files, true, true)) - return false; + return nullptr; // Keep index file in case we need it some other time (like when changing versions) QString new_index_place(FS::PathCombine(parent_folder, "modrinth.index.json")); @@ -194,7 +194,7 @@ bool ModrinthCreationTask::createInstance() // Apply the overrides if (!FS::move(override_path, mcPath)) { setError(tr("Could not rename the overrides folder:\n") + "overrides"); - return false; + return nullptr; } } @@ -207,15 +207,15 @@ bool ModrinthCreationTask::createInstance() // Apply the overrides if (!FS::overrideFolder(mcPath, client_override_path)) { setError(tr("Could not rename the client overrides folder:\n") + "client overrides"); - return false; + return nullptr; } } QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg"); auto instanceSettings = std::make_unique(configPath); - MinecraftInstance instance(m_globalSettings, std::move(instanceSettings), m_stagingPath); + auto instance = std::make_unique(m_globalSettings, std::move(instanceSettings), m_stagingPath); - auto components = instance.getPackProfile(); + auto components = instance->getPackProfile(); components->buildingFromScratch(); components->setComponentVersion("net.minecraft", m_minecraft_version, true); @@ -229,19 +229,19 @@ bool ModrinthCreationTask::createInstance() components->setComponentVersion("net.neoforged", m_neoForge_version); if (m_instIcon != "default") { - instance.setIconKey(m_instIcon); + instance->setIconKey(m_instIcon); } else if (!m_managed_id.isEmpty()) { - instance.setIconKey("modrinth"); + instance->setIconKey("modrinth"); } // Don't add managed info to packs without an ID (most likely imported from ZIP) if (!m_managed_id.isEmpty()) - instance.setManagedPack("modrinth", m_managed_id, m_managed_name, m_managed_version_id, version()); + instance->setManagedPack("modrinth", m_managed_id, m_managed_name, m_managed_version_id, version()); else - instance.setManagedPack("modrinth", "", name(), "", ""); + instance->setManagedPack("modrinth", "", name(), "", ""); - instance.setName(name()); - instance.saveNow(); + instance->setName(name()); + instance->saveNow(); auto downloadMods = makeShared(tr("Mod Download Modrinth"), APPLICATION->network()); @@ -257,7 +257,7 @@ bool ModrinthCreationTask::createInstance() // This means we somehow got out of the root folder, so abort here to prevent exploits setError(tr("One of the files has a path that leads to an arbitrary location (%1). This is a security risk and isn't allowed.") .arg(fileName)); - return false; + return nullptr; } if (fileName.startsWith("mods/")) { auto mod = new Mod(file_path); @@ -268,7 +268,7 @@ bool ModrinthCreationTask::createInstance() } if (file.downloads.empty()) { setError(tr("The file '%1' is missing a download link. This is invalid in the pack format.").arg(fileName)); - return false; + return nullptr; } qDebug() << "Will try to download" << file.downloads.front() << "to" << file_path; auto dl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path); @@ -312,11 +312,11 @@ bool ModrinthCreationTask::createInstance() for (auto resource : resources) { delete resource; } - return ended_well; + return nullptr; } QEventLoop ensureMetaLoop; - QDir folder = FS::PathCombine(instance.modsRoot(), ".index"); + QDir folder = FS::PathCombine(instance->modsRoot(), ".index"); auto ensureMetadataTask = makeShared(resources, folder, ModPlatform::ResourceProvider::MODRINTH); connect(ensureMetadataTask.get(), &Task::succeeded, this, [&ended_well]() { ended_well = true; }); connect(ensureMetadataTask.get(), &Task::finished, &ensureMetaLoop, &QEventLoop::quit); @@ -343,15 +343,18 @@ bool ModrinthCreationTask::createInstance() // Only change the name if it didn't use a custom name, so that the previous custom name // is preserved, but if we're using the original one, we update the version string. // NOTE: This needs to come before the copyManagedPack call! - if (inst->name().contains(inst->getManagedPackVersionName()) && inst->name() != instance.name()) { - if (askForChangingInstanceName(m_parent, inst->name(), instance.name()) == InstanceNameChange::ShouldChange) - inst->setName(instance.name()); + if (inst->name().contains(inst->getManagedPackVersionName()) && inst->name() != instance->name()) { + if (askForChangingInstanceName(m_parent, inst->name(), instance->name()) == InstanceNameChange::ShouldChange) + inst->setName(instance->name()); } - inst->copyManagedPack(instance); + inst->copyManagedPack(*instance); } - return ended_well; + if (ended_well) { + return instance; + } + return nullptr; } bool ModrinthCreationTask::parseManifest(const QString& index_path, diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h index bda91edf6..01cc8755a 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h @@ -41,7 +41,7 @@ class ModrinthCreationTask final : public InstanceCreationTask { bool abort() override; bool updateInstance() override; - bool createInstance() override; + std::unique_ptr createInstance() override; private: bool parseManifest(const QString&, std::vector&, bool set_internal_data = true, bool show_optional_dialog = true); From 625f0060a1ef9576f51783481e20087d1c60b7f1 Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Mon, 2 Feb 2026 16:06:02 +0500 Subject: [PATCH 2/9] feat: download game files during instance creation Signed-off-by: Octol1ttle --- launcher/InstanceCreationTask.cpp | 51 +++++++++++++++++-- launcher/InstanceCreationTask.h | 4 ++ launcher/InstanceList.cpp | 4 +- .../flame/FlameInstanceCreationTask.cpp | 3 +- .../modrinth/ModrinthInstanceCreationTask.cpp | 3 +- 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/launcher/InstanceCreationTask.cpp b/launcher/InstanceCreationTask.cpp index 94c229128..5f87b001d 100644 --- a/launcher/InstanceCreationTask.cpp +++ b/launcher/InstanceCreationTask.cpp @@ -2,7 +2,23 @@ #include #include -#include "FileSystem.h" + +#include "minecraft/MinecraftLoadAndCheck.h" +#include "tasks/SequentialTask.h" + +bool InstanceCreationTask::abort() +{ + if (!canAbort()) { + return false; + } + + m_abort = true; + if (m_gameFilesTask) { + return m_gameFilesTask->abort(); + } + + return true; +} void InstanceCreationTask::executeTask() { @@ -19,7 +35,8 @@ void InstanceCreationTask::executeTask() return; } - if (!createInstance()) { + m_instance = createInstance(); + if (!m_instance) { if (m_abort) return; @@ -61,6 +78,32 @@ void InstanceCreationTask::executeTask() return; } } - if (!m_abort) - emitSucceeded(); + + if (!m_abort) { + setAbortable(true); + setStatus(tr("Downloading game files")); + qDebug() << "Downloading game files"; + + auto updateTasks = m_instance->createUpdateTask(); + if (updateTasks.isEmpty()) { + emitSucceeded(); + return; + } + auto task = makeShared(); + task->addTask(makeShared(m_instance.get(), Net::Mode::Online)); + for (const auto& t : updateTasks) { + task->addTask(t); + } + connect(task.get(), &Task::finished, this, [this, task] { + if (task->wasSuccessful() || m_abort) { + emitSucceeded(); + } else { + emitFailed(tr("Could not download game files: %1").arg(task->failReason())); + } + }); + propagateFromOther(task.get()); + + m_gameFilesTask = task; + m_gameFilesTask->start(); + } } diff --git a/launcher/InstanceCreationTask.h b/launcher/InstanceCreationTask.h index 95dc816a2..e25afd3e9 100644 --- a/launcher/InstanceCreationTask.h +++ b/launcher/InstanceCreationTask.h @@ -10,6 +10,8 @@ class InstanceCreationTask : public InstanceTask { InstanceCreationTask() = default; virtual ~InstanceCreationTask() = default; + bool abort() override; + protected: void executeTask() final override; @@ -44,4 +46,6 @@ class InstanceCreationTask : public InstanceTask { private: QString m_error_message; + std::unique_ptr m_instance; + Task::Ptr m_gameFilesTask; }; diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index 68681a9bb..6e84111f2 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -938,9 +938,7 @@ class InstanceStaging : public Task { if (!canAbort()) return false; - m_child->abort(); - - return Task::abort(); + return m_child->abort(); } bool canAbort() const override { return (m_child && m_child->canAbort()); } diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 98cd6fb28..66475bc08 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -75,7 +75,6 @@ bool FlameCreationTask::abort() if (!canAbort()) return false; - m_abort = true; if (m_processUpdateFileInfoJob) m_processUpdateFileInfoJob->abort(); if (m_filesJob) @@ -83,7 +82,7 @@ bool FlameCreationTask::abort() if (m_modIdResolver) m_modIdResolver->abort(); - return Task::abort(); + return InstanceCreationTask::abort(); } bool FlameCreationTask::updateInstance() diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 3bc3dc755..6409c4f35 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -32,10 +32,9 @@ bool ModrinthCreationTask::abort() if (!canAbort()) return false; - m_abort = true; if (m_task) m_task->abort(); - return Task::abort(); + return InstanceCreationTask::abort(); } bool ModrinthCreationTask::updateInstance() From 7bcd2dd76847a6c039b4daf9c2b3db55968e8451 Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Mon, 2 Feb 2026 16:37:30 +0500 Subject: [PATCH 3/9] fix: properly emit aborted instead of failed Signed-off-by: Octol1ttle --- launcher/DataMigrationTask.cpp | 4 ++-- launcher/launch/LaunchTask.cpp | 2 +- launcher/launch/steps/LookupServerAddress.cpp | 2 +- launcher/launch/steps/TextPrint.cpp | 2 +- launcher/minecraft/MinecraftLoadAndCheck.cpp | 2 +- launcher/minecraft/launch/AutoInstallJava.cpp | 2 +- launcher/minecraft/update/AssetUpdateTask.cpp | 4 ++-- launcher/minecraft/update/LegacyFMLLibrariesTask.cpp | 2 +- launcher/minecraft/update/LibrariesTask.cpp | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/launcher/DataMigrationTask.cpp b/launcher/DataMigrationTask.cpp index 9677f868e..cab22089e 100644 --- a/launcher/DataMigrationTask.cpp +++ b/launcher/DataMigrationTask.cpp @@ -63,7 +63,7 @@ void DataMigrationTask::dryRunFinished() void DataMigrationTask::dryRunAborted() { - emitFailed(tr("Aborted")); + emitAborted(); } void DataMigrationTask::copyFinished() @@ -81,5 +81,5 @@ void DataMigrationTask::copyFinished() void DataMigrationTask::copyAborted() { - emitFailed(tr("Aborted")); + emitAborted(); } diff --git a/launcher/launch/LaunchTask.cpp b/launcher/launch/LaunchTask.cpp index e6230b17c..26b2b582d 100644 --- a/launcher/launch/LaunchTask.cpp +++ b/launcher/launch/LaunchTask.cpp @@ -180,7 +180,7 @@ bool LaunchTask::abort() return true; case LaunchTask::NotStarted: { state = LaunchTask::Aborted; - emitFailed("Aborted"); + emitAborted(); return true; } case LaunchTask::Running: diff --git a/launcher/launch/steps/LookupServerAddress.cpp b/launcher/launch/steps/LookupServerAddress.cpp index fdd9fc545..cb2f5d7de 100644 --- a/launcher/launch/steps/LookupServerAddress.cpp +++ b/launcher/launch/steps/LookupServerAddress.cpp @@ -38,7 +38,7 @@ void LookupServerAddress::setOutputAddressPtr(MinecraftTarget::Ptr output) bool LookupServerAddress::abort() { m_dnsLookup->abort(); - emitFailed("Aborted"); + emitAborted(); return true; } diff --git a/launcher/launch/steps/TextPrint.cpp b/launcher/launch/steps/TextPrint.cpp index 53aff807e..f96d11343 100644 --- a/launcher/launch/steps/TextPrint.cpp +++ b/launcher/launch/steps/TextPrint.cpp @@ -24,6 +24,6 @@ bool TextPrint::canAbort() const bool TextPrint::abort() { - emitFailed("Aborted."); + emitAborted(); return true; } diff --git a/launcher/minecraft/MinecraftLoadAndCheck.cpp b/launcher/minecraft/MinecraftLoadAndCheck.cpp index 198076cc4..c26fb8b60 100644 --- a/launcher/minecraft/MinecraftLoadAndCheck.cpp +++ b/launcher/minecraft/MinecraftLoadAndCheck.cpp @@ -20,7 +20,7 @@ void MinecraftLoadAndCheck::executeTask() } connect(m_task.get(), &Task::succeeded, this, &MinecraftLoadAndCheck::emitSucceeded); connect(m_task.get(), &Task::failed, this, &MinecraftLoadAndCheck::emitFailed); - connect(m_task.get(), &Task::aborted, this, [this] { emitFailed(tr("Aborted")); }); + connect(m_task.get(), &Task::aborted, this, &MinecraftLoadAndCheck::emitAborted); propagateFromOther(m_task.get()); } diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index 6a2bcb311..f60780f1b 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -244,7 +244,7 @@ bool AutoInstallJava::abort() { if (m_current_task && m_current_task->canAbort()) { auto status = m_current_task->abort(); - emitFailed("Aborted."); + emitAborted(); return status; } return Task::abort(); diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp index 55683956f..22eea47b2 100644 --- a/launcher/minecraft/update/AssetUpdateTask.cpp +++ b/launcher/minecraft/update/AssetUpdateTask.cpp @@ -39,7 +39,7 @@ void AssetUpdateTask::executeTask() connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::assetIndexFinished); connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetIndexFailed); - connect(downloadJob.get(), &NetJob::aborted, this, [this] { emitFailed(tr("Aborted")); }); + connect(downloadJob.get(), &NetJob::aborted, this, &AssetUpdateTask::emitAborted); connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress); connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress); @@ -82,7 +82,7 @@ void AssetUpdateTask::assetIndexFinished() downloadJob = job; connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::emitSucceeded); connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetsFailed); - connect(downloadJob.get(), &NetJob::aborted, this, [this] { emitFailed(tr("Aborted")); }); + connect(downloadJob.get(), &NetJob::aborted, this, &AssetUpdateTask::emitAborted); connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress); connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress); downloadJob->start(); diff --git a/launcher/minecraft/update/LegacyFMLLibrariesTask.cpp b/launcher/minecraft/update/LegacyFMLLibrariesTask.cpp index bd817a572..a3bcc145f 100644 --- a/launcher/minecraft/update/LegacyFMLLibrariesTask.cpp +++ b/launcher/minecraft/update/LegacyFMLLibrariesTask.cpp @@ -70,7 +70,7 @@ void LegacyFMLLibrariesTask::executeTask() connect(dljob.get(), &NetJob::succeeded, this, &LegacyFMLLibrariesTask::fmllibsFinished); connect(dljob.get(), &NetJob::failed, this, &LegacyFMLLibrariesTask::fmllibsFailed); - connect(dljob.get(), &NetJob::aborted, this, [this] { emitFailed(tr("Aborted")); }); + connect(dljob.get(), &NetJob::aborted, this, &LegacyFMLLibrariesTask::emitAborted); connect(dljob.get(), &NetJob::progress, this, &LegacyFMLLibrariesTask::progress); connect(dljob.get(), &NetJob::stepProgress, this, &LegacyFMLLibrariesTask::propagateStepProgress); downloadJob.reset(dljob); diff --git a/launcher/minecraft/update/LibrariesTask.cpp b/launcher/minecraft/update/LibrariesTask.cpp index 85f4103cd..c09be2156 100644 --- a/launcher/minecraft/update/LibrariesTask.cpp +++ b/launcher/minecraft/update/LibrariesTask.cpp @@ -64,7 +64,7 @@ void LibrariesTask::executeTask() connect(downloadJob.get(), &NetJob::succeeded, this, &LibrariesTask::emitSucceeded); connect(downloadJob.get(), &NetJob::failed, this, &LibrariesTask::jarlibFailed); - connect(downloadJob.get(), &NetJob::aborted, this, [this] { emitFailed(tr("Aborted")); }); + connect(downloadJob.get(), &NetJob::aborted, this, &LibrariesTask::emitAborted); connect(downloadJob.get(), &NetJob::progress, this, &LibrariesTask::progress); connect(downloadJob.get(), &NetJob::stepProgress, this, &LibrariesTask::propagateStepProgress); From f085a0ef25ed00b925ccdc34926ff285e1a98850 Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Mon, 2 Feb 2026 16:39:25 +0500 Subject: [PATCH 4/9] fix: use translated "Aborted" Signed-off-by: Octol1ttle --- launcher/tasks/Task.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp index b01b2491c..a54b4e7c2 100644 --- a/launcher/tasks/Task.cpp +++ b/launcher/tasks/Task.cpp @@ -131,7 +131,7 @@ void Task::emitAborted() return; } m_state = State::AbortedByUser; - m_failReason = "Aborted."; + m_failReason = tr("Aborted"); if (m_show_debug) qCDebug(taskLogC) << "Task" << describe() << "aborted."; emit aborted(); From d464c1ea68e461c4eee9917482d0f23c8b4cd279 Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Mon, 2 Feb 2026 16:44:49 +0500 Subject: [PATCH 5/9] fix: properly set details in InstanceCreationTask Signed-off-by: Octol1ttle --- launcher/InstanceCreationTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/InstanceCreationTask.cpp b/launcher/InstanceCreationTask.cpp index 5f87b001d..accf5cca6 100644 --- a/launcher/InstanceCreationTask.cpp +++ b/launcher/InstanceCreationTask.cpp @@ -81,7 +81,6 @@ void InstanceCreationTask::executeTask() if (!m_abort) { setAbortable(true); - setStatus(tr("Downloading game files")); qDebug() << "Downloading game files"; auto updateTasks = m_instance->createUpdateTask(); @@ -102,6 +101,7 @@ void InstanceCreationTask::executeTask() } }); propagateFromOther(task.get()); + setDetails(tr("Downloading game files")); m_gameFilesTask = task; m_gameFilesTask->start(); From 4afbd9da01124b373b62f498c94418588c47687c Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Mon, 2 Feb 2026 17:08:57 +0500 Subject: [PATCH 6/9] oops Signed-off-by: Octol1ttle --- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 66475bc08..2120a45cd 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -544,7 +544,7 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) BlockedModsDialog message_dialog(m_parent, tr("Blocked mods found"), tr("The following files are not available for download in third party launchers.
" - "You will need to manually download them and add them to the instance->"), + "You will need to manually download them and add them to the instance."), blocked_mods); message_dialog.setModal(true); From 31971b2746732c351c0af2c781d52517af030e6f Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Mon, 2 Feb 2026 19:42:56 +0500 Subject: [PATCH 7/9] fix: don't return instance if creation didn't succeed Signed-off-by: Octol1ttle --- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 2120a45cd..ebc15aea1 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -487,7 +487,10 @@ std::unique_ptr FlameCreationTask::createInstance() inst->copyManagedPack(*instance); } - return instance; + if (did_succeed) { + return instance; + } + return nullptr; } void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) From f59e5b2df98bce27ab69c2a4e2b291b0693c7e08 Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Tue, 10 Feb 2026 22:42:19 +0500 Subject: [PATCH 8/9] change: set abort button to "Skip" when downloading game files Signed-off-by: Octol1ttle --- launcher/InstanceCreationTask.cpp | 1 + launcher/InstanceList.cpp | 1 + launcher/tasks/Task.h | 7 +++++++ launcher/ui/dialogs/ProgressDialog.cpp | 1 + 4 files changed, 10 insertions(+) diff --git a/launcher/InstanceCreationTask.cpp b/launcher/InstanceCreationTask.cpp index accf5cca6..1f0cc99c8 100644 --- a/launcher/InstanceCreationTask.cpp +++ b/launcher/InstanceCreationTask.cpp @@ -81,6 +81,7 @@ void InstanceCreationTask::executeTask() if (!m_abort) { setAbortable(true); + setAbortButtonText(tr("Skip")); qDebug() << "Downloading game files"; auto updateTasks = m_instance->createUpdateTask(); diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index 6e84111f2..2bab7f635 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -923,6 +923,7 @@ class InstanceStaging : public Task { connect(child, &Task::failed, this, &InstanceStaging::childFailed); connect(child, &Task::aborted, this, &InstanceStaging::childAborted); connect(child, &Task::abortStatusChanged, this, &InstanceStaging::setAbortable); + connect(child, &Task::abortButtonTextChanged, this, &InstanceStaging::setAbortButtonText); connect(child, &Task::status, this, &InstanceStaging::setStatus); connect(child, &Task::details, this, &InstanceStaging::setDetails); connect(child, &Task::progress, this, &InstanceStaging::setProgress); diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h index 6e7645338..94fb57783 100644 --- a/launcher/tasks/Task.h +++ b/launcher/tasks/Task.h @@ -154,6 +154,8 @@ class Task : public QObject, public QRunnable { //! Emitted when the canAbort() status has changed. */ void abortStatusChanged(bool can_abort); + void abortButtonTextChanged(QString text); + public slots: // QRunnable's interface void run() override { start(); } @@ -174,6 +176,11 @@ class Task : public QObject, public QRunnable { emit abortStatusChanged(can_abort); } + void setAbortButtonText(QString text) + { + emit abortButtonTextChanged(text); + } + protected: //! The task subclass must implement this method. This method is called to start to run the task. //! The task is not finished when this method returns. the subclass must manually call emitSucceeded() or emitFailed() instead. diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index aa2f67bdb..6aa0b4bdf 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -152,6 +152,7 @@ int ProgressDialog::execWithTask(Task* task) this->m_taskConnections.push_back(connect(task, &Task::progress, this, &ProgressDialog::changeProgress)); this->m_taskConnections.push_back(connect(task, &Task::aborted, this, &ProgressDialog::hide)); this->m_taskConnections.push_back(connect(task, &Task::abortStatusChanged, ui->skipButton, &QPushButton::setEnabled)); + this->m_taskConnections.push_back(connect(task, &Task::abortButtonTextChanged, ui->skipButton, &QPushButton::setText)); m_is_multi_step = task->isMultiStep(); ui->taskProgressScrollArea->setHidden(!m_is_multi_step); From e5fe2c100e7946cb46323302f50a1b5f9ad9b1b9 Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Wed, 11 Feb 2026 20:32:36 +0500 Subject: [PATCH 9/9] change button text in Modrinth and Flame imports Signed-off-by: Octol1ttle --- launcher/InstanceImportTask.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 44f513bc7..9b04f99b6 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -322,6 +322,7 @@ void InstanceImportTask::processFlame() connect(inst_creation_task.get(), &Task::aborted, this, &InstanceImportTask::emitAborted); connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable); + connect(inst_creation_task.get(), &Task::abortButtonTextChanged, this, &Task::setAbortButtonText); connect(inst_creation_task.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); }); @@ -421,6 +422,7 @@ void InstanceImportTask::processModrinth() connect(inst_creation_task.get(), &Task::aborted, this, &InstanceImportTask::emitAborted); connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable); + connect(inst_creation_task.get(), &Task::abortButtonTextChanged, this, &Task::setAbortButtonText); connect(inst_creation_task.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });