summaryrefslogtreecommitdiff
path: root/archived/projt-launcher/launcher/minecraft/launch
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:51:45 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:51:45 +0300
commitd3261e64152397db2dca4d691a990c6bc2a6f4dd (patch)
treefac2f7be638651181a72453d714f0f96675c2b8b /archived/projt-launcher/launcher/minecraft/launch
parent31b9a8949ed0a288143e23bf739f2eb64fdc63be (diff)
downloadProject-Tick-d3261e64152397db2dca4d691a990c6bc2a6f4dd.tar.gz
Project-Tick-d3261e64152397db2dca4d691a990c6bc2a6f4dd.zip
NOISSUE add archived projects
Signed-off-by: Mehmet Samet Duman <yongdohyun@projecttick.org>
Diffstat (limited to 'archived/projt-launcher/launcher/minecraft/launch')
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/AutoInstallJava.cpp313
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/AutoInstallJava.hpp57
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ClaimAccount.cpp49
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ClaimAccount.hpp60
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/CreateGameFolders.cpp46
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/CreateGameFolders.hpp57
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ExtractNatives.cpp161
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ExtractNatives.hpp55
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/LauncherPartLaunch.cpp275
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/LauncherPartLaunch.hpp82
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/MinecraftTarget.cpp120
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/MinecraftTarget.hpp58
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ModMinecraftJar.cpp123
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ModMinecraftJar.hpp59
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/PrintInstanceInfo.cpp110
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/PrintInstanceInfo.hpp65
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ReconstructAssets.cpp57
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ReconstructAssets.hpp55
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ScanModFolders.cpp116
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/ScanModFolders.hpp67
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/VerifyJavaInstall.cpp80
-rw-r--r--archived/projt-launcher/launcher/minecraft/launch/VerifyJavaInstall.hpp40
22 files changed, 2105 insertions, 0 deletions
diff --git a/archived/projt-launcher/launcher/minecraft/launch/AutoInstallJava.cpp b/archived/projt-launcher/launcher/minecraft/launch/AutoInstallJava.cpp
new file mode 100644
index 0000000000..518953be75
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/AutoInstallJava.cpp
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "AutoInstallJava.hpp"
+#include <QDir>
+#include <QFileInfo>
+#include <memory>
+
+#include "Application.h"
+#include "FileSystem.h"
+#include "MessageLevel.h"
+#include "QObjectPtr.h"
+#include "SysInfo.h"
+#include "java/core/RuntimeInstall.hpp"
+#include "java/core/RuntimeVersion.hpp"
+#include "java/services/RuntimeCatalog.hpp"
+#include "java/services/RuntimeScanner.hpp"
+#include "java/download/RuntimeArchiveTask.hpp"
+#include "java/download/RuntimeManifestTask.hpp"
+#include "java/download/RuntimeLinkTask.hpp"
+#include "meta/Index.hpp"
+#include "minecraft/MinecraftInstance.h"
+#include "minecraft/PackProfile.h"
+#include "net/Mode.h"
+#include "tasks/SequentialTask.h"
+
+AutoInstallJava::AutoInstallJava(projt::launch::LaunchPipeline* parent)
+ : projt::launch::LaunchStage(parent),
+ m_instance(m_flow->instance()),
+ m_supported_arch(SysInfo::getSupportedJavaArchitecture()) {};
+
+void AutoInstallJava::executeTask()
+{
+ auto settings = m_instance->settings();
+ if (!APPLICATION->settings()->get("AutomaticJavaSwitch").toBool())
+ {
+ emitSucceeded();
+ return;
+ }
+ if (!settings->get("OverrideJavaLocation").toBool())
+ {
+ emitSucceeded();
+ return;
+ }
+ auto packProfile = m_instance->getPackProfile();
+ const auto configuredJavaPath = settings->get("JavaPath").toString();
+ const bool hasValidJava = !FS::ResolveExecutable(configuredJavaPath).isEmpty();
+ const bool ignoreCompatibility = settings->get("IgnoreJavaCompatibility").toBool();
+ const auto compatibleMajors = packProfile->getProfile()->getCompatibleJavaMajors();
+ bool compatibleJava = true;
+ if (!ignoreCompatibility && !compatibleMajors.isEmpty())
+ {
+ auto storedVersion = settings->get("JavaVersion").toString();
+ if (storedVersion.isEmpty())
+ {
+ compatibleJava = false;
+ }
+ else
+ {
+ projt::java::RuntimeVersion javaVersion(storedVersion);
+ compatibleJava = compatibleMajors.contains(javaVersion.major());
+ }
+ }
+ if (hasValidJava && compatibleJava)
+ {
+ emitSucceeded();
+ return;
+ }
+ if (!APPLICATION->settings()->get("AutomaticJavaDownload").toBool())
+ {
+ auto javas = APPLICATION->runtimeCatalog();
+ m_current_task = javas->getLoadTask();
+ connect(
+ m_current_task.get(),
+ &Task::finished,
+ this,
+ [this, javas, packProfile]
+ {
+ for (auto i = 0; i < javas->count(); i++)
+ {
+ auto java = std::dynamic_pointer_cast<projt::java::RuntimeInstall>(javas->at(i));
+ if (java && packProfile->getProfile()->getCompatibleJavaMajors().contains(java->version.major()))
+ {
+ if (!java->is_64bit)
+ {
+ emit logLine(tr("The automatic Java mechanism detected a 32-bit installation of Java."),
+ MessageLevel::Launcher);
+ }
+ setJavaPath(java->path);
+ return;
+ }
+ }
+ emit logLine(tr("No compatible Java version was found. Using the default one."), MessageLevel::Warning);
+ emitSucceeded();
+ });
+ connect(m_current_task.get(), &Task::progress, this, &AutoInstallJava::setProgress);
+ connect(m_current_task.get(), &Task::stepProgress, this, &AutoInstallJava::propagateStepProgress);
+ connect(m_current_task.get(), &Task::status, this, &AutoInstallJava::setStatus);
+ connect(m_current_task.get(), &Task::details, this, &AutoInstallJava::setDetails);
+ emit progressReportingRequest();
+ return;
+ }
+ if (m_supported_arch.isEmpty())
+ {
+ emit logLine(
+ tr("Your system (%1-%2) is not compatible with automatic Java installation. Using the default Java path.")
+ .arg(SysInfo::currentSystem(), SysInfo::useQTForArch()),
+ MessageLevel::Warning);
+ emitSucceeded();
+ return;
+ }
+ auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName();
+ if (wantedJavaName.isEmpty())
+ {
+ emit logLine(tr("Your meta information is out of date or doesn't have the information necessary to determine "
+ "what installation of "
+ "Java should be used. "
+ "Using the default Java path."),
+ MessageLevel::Warning);
+ emitSucceeded();
+ return;
+ }
+ QDir javaDir(APPLICATION->javaPath());
+ auto wantedJavaPath = javaDir.absoluteFilePath(wantedJavaName);
+ if (QFileInfo::exists(wantedJavaPath))
+ {
+ setJavaPathFromPartial();
+ return;
+ }
+ auto versionList = APPLICATION->metadataIndex()->component("net.minecraft.java");
+ m_current_task = versionList->getLoadTask();
+ connect(m_current_task.get(), &Task::succeeded, this, &AutoInstallJava::tryNextMajorJava);
+ connect(m_current_task.get(), &Task::failed, this, &AutoInstallJava::emitFailed);
+ connect(m_current_task.get(), &Task::progress, this, &AutoInstallJava::setProgress);
+ connect(m_current_task.get(), &Task::stepProgress, this, &AutoInstallJava::propagateStepProgress);
+ connect(m_current_task.get(), &Task::status, this, &AutoInstallJava::setStatus);
+ connect(m_current_task.get(), &Task::details, this, &AutoInstallJava::setDetails);
+ if (!m_current_task->isRunning())
+ {
+ m_current_task->start();
+ }
+ emit progressReportingRequest();
+}
+
+void AutoInstallJava::setJavaPath(QString path)
+{
+ auto settings = m_instance->settings();
+ settings->set("OverrideJavaLocation", true);
+ settings->set("JavaPath", path);
+ settings->set("AutomaticJava", true);
+ emit logLine(tr("Compatible Java found at: %1.").arg(path), MessageLevel::Launcher);
+ emitSucceeded();
+}
+
+void AutoInstallJava::setJavaPathFromPartial()
+{
+ auto packProfile = m_instance->getPackProfile();
+ auto javaName = packProfile->getProfile()->getCompatibleJavaName();
+ QDir javaDir(APPLICATION->javaPath());
+ // just checking if the executable is there should suffice
+ // but if needed this can be achieved through refreshing the javalist
+ // and retrieving the path that contains the java name
+ auto relativeBinary = FS::PathCombine(javaName, "bin", projt::java::RuntimeScanner::executableName());
+ auto finalPath = javaDir.absoluteFilePath(relativeBinary);
+ if (QFileInfo::exists(finalPath))
+ {
+ setJavaPath(finalPath);
+ }
+ else
+ {
+ emit logLine(
+ tr("No compatible Java version was found (the binary file does not exist). Using the default one."),
+ MessageLevel::Warning);
+ emitSucceeded();
+ }
+ return;
+}
+
+void AutoInstallJava::downloadJava(projt::meta::MetaVersion::Ptr version, QString javaName)
+{
+ auto runtimes = version->detailedData()->runtimes;
+ for (auto java : runtimes)
+ {
+ if (java->runtimeOS == m_supported_arch && java->name() == javaName)
+ {
+ QDir javaDir(APPLICATION->javaPath());
+ auto final_path = javaDir.absoluteFilePath(java->displayName);
+ switch (java->downloadKind)
+ {
+ case projt::java::PackageKind::Manifest:
+ m_current_task = makeShared<projt::java::RuntimeManifestTask>(java->url,
+ final_path,
+ java->checksumType,
+ java->checksumHash);
+ break;
+ case projt::java::PackageKind::Archive:
+ m_current_task = makeShared<projt::java::RuntimeArchiveTask>(java->url,
+ final_path,
+ java->checksumType,
+ java->checksumHash);
+ break;
+ case projt::java::PackageKind::Unknown:
+ emitFailed(tr("Could not determine Java download type!"));
+ return;
+ }
+#if defined(Q_OS_MACOS)
+ auto seq = makeShared<SequentialTask>(tr("Install Java"));
+ seq->addTask(m_current_task);
+ seq->addTask(makeShared<projt::java::RuntimeLinkTask>(final_path));
+ m_current_task = seq;
+#endif
+ auto deletePath = [final_path] { FS::deletePath(final_path); };
+ connect(m_current_task.get(),
+ &Task::failed,
+ this,
+ [this, deletePath](QString reason)
+ {
+ deletePath();
+ emitFailed(reason);
+ });
+ connect(m_current_task.get(), &Task::aborted, this, [deletePath] { deletePath(); });
+ connect(m_current_task.get(), &Task::succeeded, this, &AutoInstallJava::setJavaPathFromPartial);
+ connect(m_current_task.get(), &Task::failed, this, &AutoInstallJava::tryNextMajorJava);
+ connect(m_current_task.get(), &Task::progress, this, &AutoInstallJava::setProgress);
+ connect(m_current_task.get(), &Task::stepProgress, this, &AutoInstallJava::propagateStepProgress);
+ connect(m_current_task.get(), &Task::status, this, &AutoInstallJava::setStatus);
+ connect(m_current_task.get(), &Task::details, this, &AutoInstallJava::setDetails);
+ m_current_task->start();
+ return;
+ }
+ }
+ tryNextMajorJava();
+}
+
+void AutoInstallJava::tryNextMajorJava()
+{
+ if (!isRunning())
+ return;
+ auto versionList = APPLICATION->metadataIndex()->component("net.minecraft.java");
+ auto packProfile = m_instance->getPackProfile();
+ auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName();
+ auto majorJavaVersions = packProfile->getProfile()->getCompatibleJavaMajors();
+ if (m_majorJavaVersionIndex >= majorJavaVersions.length())
+ {
+ emit logLine(tr("No versions of Java were found for your operating system: %1-%2")
+ .arg(SysInfo::currentSystem(), SysInfo::useQTForArch()),
+ MessageLevel::Warning);
+ emit logLine(tr("No compatible version of Java was found. Using the default one."), MessageLevel::Warning);
+ emitSucceeded();
+ return;
+ }
+ auto majorJavaVersion = majorJavaVersions[m_majorJavaVersionIndex];
+ m_majorJavaVersionIndex++;
+
+ auto javaMajor = versionList->getMetaVersion(QString("java%1").arg(majorJavaVersion));
+ if (!javaMajor)
+ {
+ tryNextMajorJava();
+ return;
+ }
+
+ if (javaMajor->isFullyLoaded())
+ {
+ downloadJava(javaMajor, wantedJavaName);
+ }
+ else
+ {
+ m_current_task = APPLICATION->metadataIndex()->loadVersionTask("net.minecraft.java",
+ javaMajor->versionId(),
+ Net::Mode::Online);
+ connect(m_current_task.get(),
+ &Task::succeeded,
+ this,
+ [this, javaMajor, wantedJavaName] { downloadJava(javaMajor, wantedJavaName); });
+ connect(m_current_task.get(), &Task::failed, this, &AutoInstallJava::tryNextMajorJava);
+ connect(m_current_task.get(), &Task::progress, this, &AutoInstallJava::setProgress);
+ connect(m_current_task.get(), &Task::stepProgress, this, &AutoInstallJava::propagateStepProgress);
+ connect(m_current_task.get(), &Task::status, this, &AutoInstallJava::setStatus);
+ connect(m_current_task.get(), &Task::details, this, &AutoInstallJava::setDetails);
+ if (!m_current_task->isRunning())
+ {
+ m_current_task->start();
+ }
+ }
+}
+bool AutoInstallJava::abort()
+{
+ if (m_current_task && m_current_task->canAbort())
+ {
+ auto status = m_current_task->abort();
+ emitAborted();
+ return status;
+ }
+ return Task::abort();
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/AutoInstallJava.hpp b/archived/projt-launcher/launcher/minecraft/launch/AutoInstallJava.hpp
new file mode 100644
index 0000000000..93fa50818e
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/AutoInstallJava.hpp
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include <launch/LaunchStage.hpp>
+#include <launch/LaunchPipeline.hpp>
+#include "meta/Version.hpp"
+#include "minecraft/MinecraftInstance.h"
+#include "tasks/Task.h"
+
+class AutoInstallJava : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+
+ public:
+ explicit AutoInstallJava(projt::launch::LaunchPipeline* parent);
+ ~AutoInstallJava() override = default;
+
+ void executeTask() override;
+ bool canAbort() const override
+ {
+ return m_current_task ? m_current_task->canAbort() : false;
+ }
+ bool abort() override;
+
+ protected:
+ void setJavaPath(QString path);
+ void setJavaPathFromPartial();
+ void downloadJava(projt::meta::MetaVersion::Ptr version, QString javaName);
+ void tryNextMajorJava();
+
+ private:
+ MinecraftInstancePtr m_instance;
+ Task::Ptr m_current_task;
+
+ qsizetype m_majorJavaVersionIndex = 0;
+ const QString m_supported_arch;
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ClaimAccount.cpp b/archived/projt-launcher/launcher/minecraft/launch/ClaimAccount.cpp
new file mode 100644
index 0000000000..2b9150214d
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ClaimAccount.cpp
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "ClaimAccount.hpp"
+#include <launch/LaunchPipeline.hpp>
+
+#include "Application.h"
+#include "minecraft/auth/AccountList.hpp"
+
+ClaimAccount::ClaimAccount(projt::launch::LaunchPipeline* parent, AuthSessionPtr session)
+ : projt::launch::LaunchStage(parent)
+{
+ if (session->launchMode == LaunchMode::Normal)
+ {
+ auto accounts = APPLICATION->accounts();
+ m_account = accounts->getAccountByProfileName(session->player_name);
+ }
+}
+
+void ClaimAccount::executeTask()
+{
+ if (m_account)
+ {
+ lock.reset(new UseLock(m_account));
+ }
+ emitSucceeded();
+}
+
+void ClaimAccount::finalize()
+{
+ lock.reset();
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ClaimAccount.hpp b/archived/projt-launcher/launcher/minecraft/launch/ClaimAccount.hpp
new file mode 100644
index 0000000000..448e77745f
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ClaimAccount.hpp
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#pragma once
+
+#include <launch/LaunchStage.hpp>
+#include <minecraft/auth/MinecraftAccount.hpp>
+
+class ClaimAccount : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+ public:
+ explicit ClaimAccount(projt::launch::LaunchPipeline* parent, AuthSessionPtr session);
+ virtual ~ClaimAccount() = default;
+
+ void executeTask() override;
+ void finalize() override;
+ bool canAbort() const override
+ {
+ return false;
+ }
+
+ private:
+ std::unique_ptr<UseLock> lock;
+ MinecraftAccountPtr m_account;
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/CreateGameFolders.cpp b/archived/projt-launcher/launcher/minecraft/launch/CreateGameFolders.cpp
new file mode 100644
index 0000000000..039ec5fe03
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/CreateGameFolders.cpp
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "CreateGameFolders.hpp"
+#include "FileSystem.h"
+#include "launch/LaunchPipeline.hpp"
+#include "minecraft/MinecraftInstance.h"
+
+CreateGameFolders::CreateGameFolders(projt::launch::LaunchPipeline* parent) : projt::launch::LaunchStage(parent)
+{}
+
+void CreateGameFolders::executeTask()
+{
+ auto instance = m_flow->instance();
+
+ if (!FS::ensureFolderPathExists(instance->gameRoot()))
+ {
+ emit logLine("Couldn't create the main game folder", MessageLevel::Error);
+ emitFailed(tr("Couldn't create the main game folder"));
+ return;
+ }
+
+ // HACK: this is a workaround for MCL-3732 - 'server-resource-packs' folder is created.
+ if (!FS::ensureFolderPathExists(FS::PathCombine(instance->gameRoot(), "server-resource-packs")))
+ {
+ emit logLine("Couldn't create the 'server-resource-packs' folder", MessageLevel::Error);
+ }
+ emitSucceeded();
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/CreateGameFolders.hpp b/archived/projt-launcher/launcher/minecraft/launch/CreateGameFolders.hpp
new file mode 100644
index 0000000000..68c5973165
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/CreateGameFolders.hpp
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#pragma once
+
+#include <LoggedProcess.h>
+#include <launch/LaunchStage.hpp>
+#include <minecraft/auth/AuthSession.hpp>
+
+// Create the main .minecraft for the instance and any other necessary folders
+class CreateGameFolders : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+ public:
+ explicit CreateGameFolders(projt::launch::LaunchPipeline* parent);
+ virtual ~CreateGameFolders() {};
+
+ virtual void executeTask();
+ virtual bool canAbort() const
+ {
+ return false;
+ }
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ExtractNatives.cpp b/archived/projt-launcher/launcher/minecraft/launch/ExtractNatives.cpp
new file mode 100644
index 0000000000..4ac7e484dc
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ExtractNatives.cpp
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "ExtractNatives.hpp"
+#include <launch/LaunchPipeline.hpp>
+#include <minecraft/MinecraftInstance.h>
+
+#include <quazip/quazip.h>
+#include <quazip/quazipdir.h>
+#include <quazip/quazipfile.h>
+#include <quazip/quazipfileinfo.h>
+#include <QDir>
+#include "FileSystem.h"
+#include "MMCZip.h"
+
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
+
+static QString replaceSuffix(QString target, const QString& suffix, const QString& replacement)
+{
+ if (!target.endsWith(suffix))
+ {
+ return target;
+ }
+ target.resize(target.length() - suffix.length());
+ return target + replacement;
+}
+
+static bool isWithinExtractionRoot(const QDir& root, const QString& path)
+{
+ const auto cleanRoot = QDir::cleanPath(root.absolutePath());
+ const auto cleanPath = QDir::cleanPath(path);
+ return cleanPath == cleanRoot || cleanPath.startsWith(cleanRoot + '/');
+}
+
+static bool symlinkEscapesExtractionRoot(QuaZip& zip, const QString& outputPath, const QDir& root)
+{
+ QuaZipFileInfo64 info;
+ if (!zip.getCurrentFileInfo(&info) || !info.isSymbolicLink())
+ {
+ return false;
+ }
+
+ QuaZipFile linkFile(&zip);
+ if (!linkFile.open(QIODevice::ReadOnly))
+ {
+ return true;
+ }
+
+ const auto linkTarget = QFile::decodeName(linkFile.readAll());
+ linkFile.close();
+
+ QString resolvedTarget;
+ if (QDir::isAbsolutePath(linkTarget))
+ {
+ resolvedTarget = QDir::cleanPath(linkTarget);
+ }
+ else
+ {
+ const auto outputDir = QFileInfo(outputPath).dir();
+ resolvedTarget = QDir::cleanPath(outputDir.absoluteFilePath(linkTarget));
+ }
+
+ return !isWithinExtractionRoot(root, resolvedTarget);
+}
+
+static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack)
+{
+ QuaZip zip(source);
+ if (!zip.open(QuaZip::mdUnzip))
+ {
+ return false;
+ }
+ QDir directory(targetFolder);
+ if (!zip.goToFirstFile())
+ {
+ return false;
+ }
+ do
+ {
+ QString name = zip.getCurrentFileName();
+ auto lowercase = name.toLower();
+ if (applyJnilibHack)
+ {
+ name = replaceSuffix(name, ".jnilib", ".dylib");
+ }
+ QString absFilePath = directory.absoluteFilePath(name);
+ if (symlinkEscapesExtractionRoot(zip, absFilePath, directory))
+ {
+ return false;
+ }
+ if (!JlCompress::extractFile(&zip, "", absFilePath))
+ {
+ return false;
+ }
+ }
+ while (zip.goToNextFile());
+ zip.close();
+ if (zip.getZipError() != 0)
+ {
+ return false;
+ }
+ return true;
+}
+
+void ExtractNatives::executeTask()
+{
+ auto instance = m_flow->instance();
+ auto toExtract = instance->getNativeJars();
+ if (toExtract.isEmpty())
+ {
+ emitSucceeded();
+ return;
+ }
+ auto settings = instance->settings();
+
+ auto outputPath = instance->getNativePath();
+ FS::ensureFolderPathExists(outputPath);
+ auto javaVersion = instance->getRuntimeVersion();
+ bool jniHackEnabled = javaVersion.major() >= 8;
+ for (const auto& source : toExtract)
+ {
+ if (!unzipNatives(source, outputPath, jniHackEnabled))
+ {
+ const char* reason = QT_TR_NOOP("Couldn't extract native jar '%1' to destination '%2'");
+ emit logLine(QString(reason).arg(source, outputPath), MessageLevel::Fatal);
+ emitFailed(tr(reason).arg(source, outputPath));
+ }
+ }
+ emitSucceeded();
+}
+
+void ExtractNatives::finalize()
+{
+ auto instance = m_flow->instance();
+ QString target_dir = FS::PathCombine(instance->instanceRoot(), "natives/");
+ QDir dir(target_dir);
+ dir.removeRecursively();
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ExtractNatives.hpp b/archived/projt-launcher/launcher/minecraft/launch/ExtractNatives.hpp
new file mode 100644
index 0000000000..696c1ac6bf
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ExtractNatives.hpp
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#pragma once
+
+#include <launch/LaunchStage.hpp>
+
+class ExtractNatives : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+ public:
+ explicit ExtractNatives(projt::launch::LaunchPipeline* parent) : projt::launch::LaunchStage(parent) {};
+ virtual ~ExtractNatives() {};
+
+ void executeTask() override;
+ bool canAbort() const override
+ {
+ return false;
+ }
+ void finalize() override;
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/LauncherPartLaunch.cpp b/archived/projt-launcher/launcher/minecraft/launch/LauncherPartLaunch.cpp
new file mode 100644
index 0000000000..642189d4ad
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/LauncherPartLaunch.cpp
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "LauncherPartLaunch.hpp"
+
+#include <QRegularExpression>
+#include <QStandardPaths>
+#include <QStringConverter>
+
+#include "Application.h"
+#include "Commandline.h"
+#include "FileSystem.h"
+#include "launch/LaunchPipeline.hpp"
+#include "minecraft/MinecraftInstance.h"
+
+#ifdef Q_OS_LINUX
+#include "gamemode_client.h"
+#endif
+
+LauncherPartLaunch::LauncherPartLaunch(projt::launch::LaunchPipeline* parent)
+ : projt::launch::LaunchStage(parent),
+ m_process(parent->instance()->getRuntimeVersion().defaultsToUtf8() ? QStringConverter::Utf8
+ : QStringConverter::System)
+{
+ if (parent->instance()->settings()->get("CloseAfterLaunch").toBool())
+ {
+ static const QRegularExpression s_settingUser(".*Setting user.+", QRegularExpression::CaseInsensitiveOption);
+ std::shared_ptr<QMetaObject::Connection> connection{ new QMetaObject::Connection };
+ *connection = connect(&m_process,
+ &LoggedProcess::log,
+ this,
+ [connection](const QStringList& lines, [[maybe_unused]] MessageLevel::Enum level)
+ {
+ qDebug() << lines;
+ if (lines.filter(s_settingUser).length() != 0)
+ {
+ APPLICATION->closeAllWindows();
+ disconnect(*connection);
+ }
+ });
+ }
+
+ connect(&m_process, &LoggedProcess::log, this, &LauncherPartLaunch::logLines);
+ connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state);
+}
+
+void LauncherPartLaunch::executeTask()
+{
+ QString jarPath = APPLICATION->getJarPath("ProjTLaunch.jar");
+ if (jarPath.isEmpty())
+ {
+ const char* reason = QT_TR_NOOP("Launcher library could not be found. Please check your installation.");
+ emit logLine(tr(reason), MessageLevel::Fatal);
+ emitFailed(tr(reason));
+ return;
+ }
+
+ auto instance = m_flow->instance();
+
+ QString legacyJarPath;
+ if (instance->getLauncher() == "legacy" || instance->shouldApplyOnlineFixes())
+ {
+ legacyJarPath = APPLICATION->getJarPath("ProjTLaunchLegacy.jar");
+ if (legacyJarPath.isEmpty())
+ {
+ const char* reason =
+ QT_TR_NOOP("Legacy launcher library could not be found. Please check your installation.");
+ emit logLine(tr(reason), MessageLevel::Fatal);
+ emitFailed(tr(reason));
+ return;
+ }
+ }
+
+ m_launchScript = instance->createLaunchScript(m_session, m_targetToJoin);
+ QStringList args = instance->javaArguments();
+ QString allArgs = args.join(", ");
+ emit logLine("Java Arguments:\n[" + m_flow->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::Launcher);
+
+ auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString());
+
+ m_process.setProcessEnvironment(instance->createLaunchEnvironment());
+
+ // make detachable - this will keep the process running even if the object is destroyed
+ m_process.setDetachable(true);
+
+ auto classPath = instance->getClassPath();
+ classPath.prepend(jarPath);
+
+ if (!legacyJarPath.isEmpty())
+ classPath.prepend(legacyJarPath);
+
+ auto natPath = instance->getNativePath();
+#ifdef Q_OS_WIN
+ natPath = FS::getPathNameInLocal8bit(natPath);
+#endif
+ args << "-Djava.library.path=" + natPath;
+
+ args << "-cp";
+#ifdef Q_OS_WIN
+ QStringList processed;
+ for (auto& item : classPath)
+ {
+ processed << FS::getPathNameInLocal8bit(item);
+ }
+ args << processed.join(';');
+#else
+ args << classPath.join(':');
+#endif
+ args << "org.projecttick.projtlauncher.normal.EntryPoint";
+
+ qDebug() << args.join(' ');
+
+ QString wrapperCommandStr = instance->getWrapperCommand().trimmed();
+ if (!wrapperCommandStr.isEmpty())
+ {
+ wrapperCommandStr = m_flow->substituteVariables(wrapperCommandStr);
+ auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr);
+ auto wrapperCommand = wrapperArgs.takeFirst();
+ auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);
+ if (realWrapperCommand.isEmpty())
+ {
+ const char* reason = QT_TR_NOOP("The wrapper command \"%1\" couldn't be found.");
+ emit logLine(QString(reason).arg(wrapperCommand), MessageLevel::Fatal);
+ emitFailed(tr(reason).arg(wrapperCommand));
+ return;
+ }
+ emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::Launcher);
+ args.prepend(javaPath);
+ m_process.start(wrapperCommand, wrapperArgs + args);
+ }
+ else
+ {
+ m_process.start(javaPath, args);
+ }
+
+#ifdef Q_OS_LINUX
+ if (instance->settings()->get("EnableFeralGamemode").toBool()
+ && APPLICATION->capabilities() & Application::SupportsGameMode)
+ {
+ auto pid = m_process.processId();
+ if (pid)
+ {
+ gamemode_request_start_for(pid);
+ }
+ }
+#endif
+}
+
+void LauncherPartLaunch::on_state(LoggedProcess::State state)
+{
+ switch (state)
+ {
+ case LoggedProcess::FailedToStart:
+ {
+ //: Error message displayed if instace can't start
+ const char* reason = QT_TR_NOOP("Could not launch Minecraft!");
+ emit logLine(reason, MessageLevel::Fatal);
+ emitFailed(tr(reason));
+ return;
+ }
+ case LoggedProcess::Aborted:
+ case LoggedProcess::Crashed:
+ {
+ m_flow->setPid(-1);
+ m_flow->instance()->setMinecraftRunning(false);
+ emitFailed(tr("Game crashed."));
+ return;
+ }
+ case LoggedProcess::Finished:
+ {
+ auto instance = m_flow->instance();
+ if (instance->settings()->get("CloseAfterLaunch").toBool())
+ APPLICATION->showMainWindow();
+
+ m_flow->setPid(-1);
+ m_flow->instance()->setMinecraftRunning(false);
+ // if the exit code wasn't 0, report this as a crash
+ auto exitCode = m_process.exitCode();
+ if (exitCode != 0)
+ {
+ emitFailed(tr("Game crashed."));
+ return;
+ }
+
+ // Set exit code in environment for post-launch hooks
+ auto env = m_process.processEnvironment();
+ env.insert("INST_EXITCODE", QString::number(exitCode));
+ env.insert("INST_NAME", instance->name());
+ env.insert("INST_ID", instance->id());
+ env.insert("INST_DIR", instance->instanceRoot());
+ // Post-launch command can be retrieved from instance settings
+ QString postExitCmd = instance->settings()->get("PostExitCommand").toString();
+ if (!postExitCmd.isEmpty())
+ {
+ emit logLine(tr("Running post-exit command: %1").arg(postExitCmd), MessageLevel::Launcher);
+ QProcess postProcess;
+ postProcess.setProcessEnvironment(env);
+ postProcess.setWorkingDirectory(instance->instanceRoot());
+ postProcess.start(postExitCmd);
+ postProcess.waitForFinished(30000); // 30 second timeout
+ if (postProcess.exitCode() != 0)
+ {
+ emit logLine(tr("Post-exit command failed with code %1").arg(postProcess.exitCode()),
+ MessageLevel::Warning);
+ }
+ }
+
+ emitSucceeded();
+ break;
+ }
+ case LoggedProcess::Running:
+ emit logLine(QString("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::Launcher);
+ m_flow->setPid(m_process.processId());
+ // send the launch script to the launcher part
+ m_process.write(m_launchScript.toUtf8());
+
+ mayProceed = true;
+ emit readyForLaunch();
+ break;
+ default: break;
+ }
+}
+
+void LauncherPartLaunch::setWorkingDirectory(const QString& wd)
+{
+ m_process.setWorkingDirectory(wd);
+}
+
+void LauncherPartLaunch::proceed()
+{
+ if (mayProceed)
+ {
+ m_flow->instance()->setMinecraftRunning(true);
+ QString launchString("launch\n");
+ m_process.write(launchString.toUtf8());
+ mayProceed = false;
+ }
+}
+
+bool LauncherPartLaunch::abort()
+{
+ if (mayProceed)
+ {
+ mayProceed = false;
+ QString launchString("abort\n");
+ m_process.write(launchString.toUtf8());
+ }
+ else
+ {
+ auto state = m_process.state();
+ if (state == LoggedProcess::Running || state == LoggedProcess::Starting)
+ {
+ m_process.kill();
+ }
+ }
+ return true;
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/LauncherPartLaunch.hpp b/archived/projt-launcher/launcher/minecraft/launch/LauncherPartLaunch.hpp
new file mode 100644
index 0000000000..0160980391
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/LauncherPartLaunch.hpp
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#pragma once
+
+#include <LoggedProcess.h>
+#include <launch/LaunchStage.hpp>
+#include <minecraft/auth/AuthSession.hpp>
+
+#include "MinecraftTarget.hpp"
+
+class LauncherPartLaunch : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+ public:
+ explicit LauncherPartLaunch(projt::launch::LaunchPipeline* parent);
+ virtual ~LauncherPartLaunch() = default;
+
+ virtual void executeTask();
+ virtual bool abort();
+ virtual void proceed();
+ virtual bool canAbort() const
+ {
+ return true;
+ }
+ void setWorkingDirectory(const QString& wd);
+ void setAuthSession(AuthSessionPtr session)
+ {
+ m_session = session;
+ }
+
+ void setTargetToJoin(MinecraftTarget::Ptr targetToJoin)
+ {
+ m_targetToJoin = std::move(targetToJoin);
+ }
+
+ private slots:
+ void on_state(LoggedProcess::State state);
+
+ private:
+ LoggedProcess m_process;
+ QString m_command;
+ AuthSessionPtr m_session;
+ QString m_launchScript;
+ MinecraftTarget::Ptr m_targetToJoin;
+
+ bool mayProceed = false;
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/MinecraftTarget.cpp b/archived/projt-launcher/launcher/minecraft/launch/MinecraftTarget.cpp
new file mode 100644
index 0000000000..5590ac05ed
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/MinecraftTarget.cpp
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#include "MinecraftTarget.hpp"
+
+#include <QRegularExpression>
+#include <QStringList>
+
+// Note: This parser intentionally mirrors Minecraft's address parsing behavior exactly,
+// including its tolerance for malformed input. Invalid addresses resolve to unusable
+// targets, which Minecraft handles at connection time. The isValid() method can be
+// used by callers requiring validation.
+MinecraftTarget MinecraftTarget::parse(const QString& fullAddress, bool useWorld)
+{
+ // Validate input - empty or whitespace-only addresses are invalid
+ QString trimmed = fullAddress.trimmed();
+ if (trimmed.isEmpty())
+ {
+ return MinecraftTarget{}; // Return empty target for invalid input
+ }
+
+ if (useWorld)
+ {
+ MinecraftTarget target;
+ target.world = trimmed;
+ return target;
+ }
+
+ QStringList split = trimmed.split(":");
+
+ // The logic below replicates the exact logic minecraft uses for parsing server addresses.
+ // While the conversion is not lossless and eats errors, it ensures the same behavior
+ // within Minecraft and ProjT Launcher when entering server addresses.
+ if (trimmed.startsWith("["))
+ {
+ int bracket = trimmed.indexOf("]");
+ if (bracket > 0)
+ {
+ QString ipv6 = trimmed.mid(1, bracket - 1);
+ QString port = trimmed.mid(bracket + 1).trimmed();
+
+ if (port.startsWith(":") && !ipv6.isEmpty())
+ {
+ port = port.mid(1);
+ split = QStringList({ ipv6, port });
+ }
+ else
+ {
+ split = QStringList({ ipv6 });
+ }
+ }
+ }
+
+ if (split.size() > 2)
+ {
+ split = QStringList({ trimmed });
+ }
+
+ QString realAddress = split[0];
+
+ // Validate address is not empty after parsing
+ if (realAddress.isEmpty())
+ {
+ return MinecraftTarget{}; // Invalid address
+ }
+
+ quint16 realPort = 25565;
+ if (split.size() > 1)
+ {
+ bool ok;
+ uint portValue = split[1].toUInt(&ok);
+
+ // Validate port is in valid range (1-65535)
+ if (ok && portValue > 0 && portValue <= 65535)
+ {
+ realPort = static_cast<quint16>(portValue);
+ }
+ else
+ {
+ // Invalid port, use default
+ realPort = 25565;
+ }
+ }
+
+ return MinecraftTarget{ realAddress, realPort };
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/MinecraftTarget.hpp b/archived/projt-launcher/launcher/minecraft/launch/MinecraftTarget.hpp
new file mode 100644
index 0000000000..11ff4b9bab
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/MinecraftTarget.hpp
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#pragma once
+
+#include <memory>
+
+#include <QString>
+
+struct MinecraftTarget
+{
+ QString address;
+ quint16 port;
+
+ QString world;
+ static MinecraftTarget parse(const QString& fullAddress, bool useWorld);
+
+ bool isValid() const
+ {
+ return !address.isEmpty() || !world.isEmpty();
+ }
+
+ using Ptr = std::shared_ptr<MinecraftTarget>;
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ModMinecraftJar.cpp b/archived/projt-launcher/launcher/minecraft/launch/ModMinecraftJar.cpp
new file mode 100644
index 0000000000..f635420498
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ModMinecraftJar.cpp
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ======================================================================== */
+
+#include "ModMinecraftJar.hpp"
+#include "FileSystem.h"
+#include "MMCZip.h"
+#include "launch/LaunchPipeline.hpp"
+#include "minecraft/MinecraftInstance.h"
+#include "minecraft/PackProfile.h"
+
+void ModMinecraftJar::executeTask()
+{
+ auto m_inst = m_flow->instance();
+
+ if (!m_inst->getJarMods().size())
+ {
+ emitSucceeded();
+ return;
+ }
+ // nuke obsolete stripped jar(s) if needed
+ if (!FS::ensureFolderPathExists(m_inst->binRoot()))
+ {
+ emitFailed(tr("Couldn't create the bin folder for Minecraft.jar"));
+ }
+
+ auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar");
+ if (!removeJar())
+ {
+ emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath));
+ }
+
+ // create temporary modded jar, if needed
+ auto components = m_inst->getPackProfile();
+ auto profile = components->getProfile();
+ auto jarMods = m_inst->getJarMods();
+ if (jarMods.size())
+ {
+ auto mainJar = profile->getMainJar();
+ QStringList jars, temp1, temp2, temp3, temp4;
+ mainJar->getApplicableFiles(m_inst->runtimeContext(), jars, temp1, temp2, temp3, m_inst->getLocalLibraryPath());
+ auto sourceJarPath = jars[0];
+ if (!MMCZip::createModdedJar(sourceJarPath, finalJarPath, jarMods))
+ {
+ emitFailed(tr("Failed to create the custom Minecraft jar file."));
+ return;
+ }
+ }
+ emitSucceeded();
+}
+
+void ModMinecraftJar::finalize()
+{
+ removeJar();
+}
+
+bool ModMinecraftJar::removeJar()
+{
+ auto m_inst = m_flow->instance();
+ auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar");
+ QFile finalJar(finalJarPath);
+ if (finalJar.exists())
+ {
+ if (!finalJar.remove())
+ {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ModMinecraftJar.hpp b/archived/projt-launcher/launcher/minecraft/launch/ModMinecraftJar.hpp
new file mode 100644
index 0000000000..0dee222941
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ModMinecraftJar.hpp
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#pragma once
+
+#include <launch/LaunchStage.hpp>
+#include <memory>
+
+class ModMinecraftJar : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+ public:
+ explicit ModMinecraftJar(projt::launch::LaunchPipeline* parent) : projt::launch::LaunchStage(parent) {};
+ virtual ~ModMinecraftJar() {};
+
+ virtual void executeTask() override;
+ virtual bool canAbort() const override
+ {
+ return false;
+ }
+ void finalize() override;
+
+ private:
+ bool removeJar();
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/PrintInstanceInfo.cpp b/archived/projt-launcher/launcher/minecraft/launch/PrintInstanceInfo.cpp
new file mode 100644
index 0000000000..186254353c
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/PrintInstanceInfo.cpp
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+#include <QSysInfo>
+#include <launch/LaunchPipeline.hpp>
+#include "PrintInstanceInfo.hpp"
+
+#include "HardwareInfo.h"
+
+#if defined(Q_OS_FREEBSD)
+namespace
+{
+ void runSysctlHwModel(QStringList& log)
+ {
+ char buff[512];
+ FILE* hwmodel = popen("sysctl hw.model", "r");
+ while (fgets(buff, 512, hwmodel) != nullptr)
+ {
+ log << QString::fromUtf8(buff);
+ break;
+ }
+ pclose(hwmodel);
+ }
+
+ void runPciconf(QStringList& log)
+ {
+ char buff[512];
+ std::string strcard;
+ FILE* pciconf = popen("pciconf -lv -a vgapci0", "r");
+ while (fgets(buff, 512, pciconf) != nullptr)
+ {
+ if (strncmp(buff, " vendor", 10) == 0)
+ {
+ std::string str(buff);
+ strcard.append(
+ str.substr(str.find_first_of("'") + 1, str.find_last_not_of("'") - (str.find_first_of("'") + 2)));
+ strcard.append(" ");
+ }
+ else if (strncmp(buff, " device", 10) == 0)
+ {
+ std::string str2(buff);
+ strcard.append(
+ str2.substr(str2.find_first_of("'") + 1, str2.find_last_not_of("'") - (str2.find_first_of("'") + 2)));
+ }
+ log << QString::fromStdString(strcard);
+ break;
+ }
+ pclose(pciconf);
+ }
+} // namespace
+#endif
+
+void PrintInstanceInfo::executeTask()
+{
+ auto instance = m_flow->instance();
+ QStringList log;
+
+ log << "OS: " + QString("%1 | %2 | %3").arg(QSysInfo::prettyProductName(), QSysInfo::kernelType(), QSysInfo::kernelVersion());
+#ifdef Q_OS_FREEBSD
+ ::runSysctlHwModel(log);
+ ::runPciconf(log);
+#else
+ log << "CPU: " + HardwareInfo::cpuInfo();
+ log << QString("RAM: %1 MiB (available: %2 MiB)").arg(HardwareInfo::totalRamMiB()).arg(HardwareInfo::availableRamMiB());
+#endif
+ log.append(HardwareInfo::gpuInfo());
+ log << "";
+
+ logLines(log, MessageLevel::Launcher);
+ logLines(instance->verboseDescription(m_session, m_targetToJoin), MessageLevel::Launcher);
+ emitSucceeded();
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/PrintInstanceInfo.hpp b/archived/projt-launcher/launcher/minecraft/launch/PrintInstanceInfo.hpp
new file mode 100644
index 0000000000..10bf98a66d
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/PrintInstanceInfo.hpp
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#pragma once
+
+#include <launch/LaunchStage.hpp>
+#include "minecraft/auth/AuthSession.hpp"
+#include "minecraft/launch/MinecraftTarget.hpp"
+
+class PrintInstanceInfo : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+ public:
+ explicit PrintInstanceInfo(projt::launch::LaunchPipeline* parent,
+ AuthSessionPtr session,
+ MinecraftTarget::Ptr targetToJoin)
+ : projt::launch::LaunchStage(parent),
+ m_session(session),
+ m_targetToJoin(targetToJoin) {};
+ virtual ~PrintInstanceInfo() = default;
+
+ virtual void executeTask();
+ virtual bool canAbort() const
+ {
+ return false;
+ }
+
+ private:
+ AuthSessionPtr m_session;
+ MinecraftTarget::Ptr m_targetToJoin;
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ReconstructAssets.cpp b/archived/projt-launcher/launcher/minecraft/launch/ReconstructAssets.cpp
new file mode 100644
index 0000000000..9f719f3539
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ReconstructAssets.cpp
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#include "ReconstructAssets.hpp"
+#include "launch/LaunchPipeline.hpp"
+#include "minecraft/AssetsUtils.h"
+#include "minecraft/MinecraftInstance.h"
+#include "minecraft/PackProfile.h"
+
+void ReconstructAssets::executeTask()
+{
+ auto instance = m_flow->instance();
+ auto components = instance->getPackProfile();
+ auto profile = components->getProfile();
+ auto assets = profile->getMinecraftAssets();
+
+ if (!AssetsUtils::reconstructAssets(assets->id, instance->resourcesDir()))
+ {
+ emit logLine("Failed to reconstruct Minecraft assets.", MessageLevel::Error);
+ }
+
+ emitSucceeded();
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ReconstructAssets.hpp b/archived/projt-launcher/launcher/minecraft/launch/ReconstructAssets.hpp
new file mode 100644
index 0000000000..715d78cbd4
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ReconstructAssets.hpp
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#pragma once
+
+#include <launch/LaunchStage.hpp>
+#include <memory>
+
+class ReconstructAssets : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+ public:
+ explicit ReconstructAssets(projt::launch::LaunchPipeline* parent) : projt::launch::LaunchStage(parent) {};
+ virtual ~ReconstructAssets() {};
+
+ void executeTask() override;
+ bool canAbort() const override
+ {
+ return false;
+ }
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ScanModFolders.cpp b/archived/projt-launcher/launcher/minecraft/launch/ScanModFolders.cpp
new file mode 100644
index 0000000000..bad7feca25
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ScanModFolders.cpp
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ======================================================================== */
+
+#include "ScanModFolders.hpp"
+#include "FileSystem.h"
+#include "MMCZip.h"
+#include "launch/LaunchPipeline.hpp"
+#include "minecraft/MinecraftInstance.h"
+#include "minecraft/mod/ModFolderModel.hpp"
+
+void ScanModFolders::executeTask()
+{
+ auto m_inst = m_flow->instance();
+
+ auto loaders = m_inst->loaderModList();
+ connect(loaders.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::modsDone);
+ if (!loaders->update())
+ {
+ m_modsDone = true;
+ }
+
+ auto cores = m_inst->coreModList();
+ connect(cores.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::coreModsDone);
+ if (!cores->update())
+ {
+ m_coreModsDone = true;
+ }
+
+ auto nils = m_inst->nilModList();
+ connect(nils.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::nilModsDone);
+ if (!nils->update())
+ {
+ m_nilModsDone = true;
+ }
+ checkDone();
+}
+
+void ScanModFolders::modsDone()
+{
+ m_modsDone = true;
+ checkDone();
+}
+
+void ScanModFolders::coreModsDone()
+{
+ m_coreModsDone = true;
+ checkDone();
+}
+
+void ScanModFolders::nilModsDone()
+{
+ m_nilModsDone = true;
+ checkDone();
+}
+
+void ScanModFolders::checkDone()
+{
+ if (m_modsDone && m_coreModsDone && m_nilModsDone)
+ {
+ emitSucceeded();
+ }
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/ScanModFolders.hpp b/archived/projt-launcher/launcher/minecraft/launch/ScanModFolders.hpp
new file mode 100644
index 0000000000..13648fc9d6
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/ScanModFolders.hpp
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * === Upstream License Block (Do Not Modify) ==============================
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================================== */
+
+#pragma once
+
+#include <launch/LaunchStage.hpp>
+#include <memory>
+
+class ScanModFolders : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+ public:
+ explicit ScanModFolders(projt::launch::LaunchPipeline* parent) : projt::launch::LaunchStage(parent) {};
+ virtual ~ScanModFolders() {};
+
+ virtual void executeTask() override;
+ virtual bool canAbort() const override
+ {
+ return false;
+ }
+ private slots:
+ void coreModsDone();
+ void modsDone();
+ void nilModsDone();
+
+ private:
+ void checkDone();
+
+ private: // DATA
+ bool m_modsDone = false;
+ bool m_nilModsDone = false;
+ bool m_coreModsDone = false;
+};
diff --git a/archived/projt-launcher/launcher/minecraft/launch/VerifyJavaInstall.cpp b/archived/projt-launcher/launcher/minecraft/launch/VerifyJavaInstall.cpp
new file mode 100644
index 0000000000..18c6d0efca
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/VerifyJavaInstall.cpp
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "VerifyJavaInstall.hpp"
+#include <memory>
+
+#include "Application.h"
+#include "MessageLevel.h"
+#include "java/core/RuntimeVersion.hpp"
+#include "minecraft/MinecraftInstance.h"
+#include "minecraft/PackProfile.h"
+
+void VerifyJavaInstall::executeTask()
+{
+ auto instance = m_flow->instance();
+ auto packProfile = instance->getPackProfile();
+ auto settings = instance->settings();
+ auto storedVersion = settings->get("JavaVersion").toString();
+ auto ignoreCompatibility = settings->get("IgnoreJavaCompatibility").toBool();
+ auto javaArchitecture = settings->get("JavaArchitecture").toString();
+ auto maxMemAlloc = settings->get("MaxMemAlloc").toInt();
+
+ if (javaArchitecture == "32" && maxMemAlloc > 2048)
+ {
+ emit logLine(tr("Max memory allocation exceeds the supported value.\n"
+ "The selected installation of Java is 32-bit and doesn't support more than 2048MiB of RAM.\n"
+ "The instance may not start due to this."),
+ MessageLevel::Error);
+ }
+
+ auto compatibleMajors = packProfile->getProfile()->getCompatibleJavaMajors();
+
+ projt::java::RuntimeVersion javaVersion(storedVersion);
+
+ if (compatibleMajors.isEmpty() || compatibleMajors.contains(javaVersion.major()))
+ {
+ emitSucceeded();
+ return;
+ }
+
+ if (ignoreCompatibility)
+ {
+ emit logLine(tr("Java major version is incompatible. Things might break."), MessageLevel::Warning);
+ emitSucceeded();
+ return;
+ }
+
+ emit logLine(tr("This instance is not compatible with Java version %1.\n"
+ "Please switch to one of the following Java versions for this instance:")
+ .arg(javaVersion.major()),
+ MessageLevel::Error);
+ for (auto major : compatibleMajors)
+ {
+ emit logLine(tr("Java version %1").arg(major), MessageLevel::Error);
+ }
+ emit logLine(tr("Go to instance Java settings to change your Java version or disable the Java compatibility check "
+ "if you know what "
+ "you're doing."),
+ MessageLevel::Error);
+
+ emitFailed(QString("Incompatible Java major version"));
+}
diff --git a/archived/projt-launcher/launcher/minecraft/launch/VerifyJavaInstall.hpp b/archived/projt-launcher/launcher/minecraft/launch/VerifyJavaInstall.hpp
new file mode 100644
index 0000000000..ec5961e0a7
--- /dev/null
+++ b/archived/projt-launcher/launcher/minecraft/launch/VerifyJavaInstall.hpp
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include <launch/LaunchStage.hpp>
+#include <launch/LaunchPipeline.hpp>
+
+class VerifyJavaInstall : public projt::launch::LaunchStage
+{
+ Q_OBJECT
+
+ public:
+ explicit VerifyJavaInstall(projt::launch::LaunchPipeline* parent) : projt::launch::LaunchStage(parent) {};
+ ~VerifyJavaInstall() override = default;
+
+ void executeTask() override;
+ bool canAbort() const override
+ {
+ return false;
+ }
+};