diff options
| author | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-02 18:51:45 +0300 |
|---|---|---|
| committer | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-02 18:51:45 +0300 |
| commit | d3261e64152397db2dca4d691a990c6bc2a6f4dd (patch) | |
| tree | fac2f7be638651181a72453d714f0f96675c2b8b /archived/projt-launcher/launcher/minecraft/launch | |
| parent | 31b9a8949ed0a288143e23bf739f2eb64fdc63be (diff) | |
| download | Project-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')
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; + } +}; |
