From f95856d06285a65caf0da7377f42f45c33d9603f Mon Sep 17 00:00:00 2001 From: timoreo Date: Thu, 30 Jun 2022 18:07:08 +0200 Subject: [PATCH 001/120] Add the base of java downloading Signed-off-by: timoreo --- launcher/CMakeLists.txt | 2 + launcher/JavaDownloader.cpp | 165 ++++++++++++++++++++++++++++++++++++ launcher/JavaDownloader.h | 8 ++ 3 files changed, 175 insertions(+) create mode 100644 launcher/JavaDownloader.cpp create mode 100644 launcher/JavaDownloader.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 79ac49c76..4e5508579 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -881,6 +881,8 @@ SET(LAUNCHER_SOURCES ui/instanceview/InstanceDelegate.h ui/instanceview/VisualGroup.cpp ui/instanceview/VisualGroup.h + JavaDownloader.cpp + JavaDownloader.h ) if(WIN32) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp new file mode 100644 index 000000000..43da2df01 --- /dev/null +++ b/launcher/JavaDownloader.cpp @@ -0,0 +1,165 @@ +#include "JavaDownloader.h" +#include "net/NetJob.h" +#include "Application.h" +#include "FileSystem.h" +#include "quazip.h" +#include "MMCZip.h" +#include "net/ChecksumValidator.h" + +//Quick & dirty struct to store files +struct File{ + QString path; + QString url; + QByteArray hash; +}; + +void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) { + //Query the adoptium API to get a good version + auto netJob = new NetJob(QString("JRE::QueryVersions"), APPLICATION->network()); + auto response = new QByteArray(); + netJob->addNetAction(Net::Download::makeByteArray(QUrl("https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); + QObject::connect(netJob, &NetJob::finished,[netJob, response]{ + netJob->deleteLater(); + delete response; + }); + QObject::connect(netJob, &NetJob::succeeded,[response, &OS, isLegacy] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + return; + } + auto versionArray = doc.object()[OS].toObject()[isLegacy ? "jre-legacy" : "java-runtime-gamma"].toArray(); + if(!versionArray.empty()){ + auto url = versionArray[0].toObject()["manifest"].toObject()["url"].toString(); + auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); + auto files = new QByteArray(); + + download->addNetAction(Net::Download::makeByteArray(QUrl(url), files)); + + QObject::connect(download, &NetJob::finished,[download, files]{ + download->deleteLater(); + delete files; + }); + QObject::connect(download, &NetJob::succeeded,[files, isLegacy] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *files; + return; + } + + //valid json doc, begin making jre spot + auto output = FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java/") + (isLegacy ? "java-legacy" : "java-current")); + FS::ensureFolderPathExists(output); + std::vector toDownload; + auto list = doc.object()["files"].toObject(); + for(auto element : list){ + auto obj = element.toObject(); + for(const auto& paths : obj.keys()){ + auto file = FS::PathCombine(output,paths); + + auto type = obj[paths].toObject()["type"].toString(); + if(type == "directory"){ + FS::ensureFolderPathExists(file); + }else if(type == "link"){ + //this is linux only ! + auto target = FS::PathCombine(file,"../"+obj[paths].toObject()["target"].toString()); + QFile(target).link(file); + }else if(type == "file"){ + //TODO download compressed version if it exists ? + auto raw = obj[paths].toObject()["downloads"].toObject()["raw"].toObject(); + auto f = File{file,raw["url"].toString(), QByteArray::fromHex(raw["sha1"].toString().toLatin1())}; + toDownload.push_back(f); + } + } + } + auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network()); + for(const auto& file : toDownload){ + auto dl = Net::Download::makeFile(file.url,file.path); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash)); + elementDownload->addNetAction(dl); + } + QObject::connect(elementDownload, &NetJob::finished,[elementDownload]{ + elementDownload->deleteLater(); + }); + elementDownload->start(); + }); + download->start(); + }else{ + //mojang does not have a JRE for us, let's get azul zulu + QString javaVersion = isLegacy ? QString("8.0") : QString("17.0"); + QString azulOS; + QString arch; + QString bitness; + + if(OS == "mac-os-arm64"){ + //macos arm64 + azulOS = "macos"; + arch = "arm"; + bitness = "64"; + }else if(OS == "linux-aarch64"){ + //linux aarch64 + azulOS = "linux"; + arch = "arm"; + bitness = "64"; + } + auto metaResponse = new QByteArray(); + auto downloadJob = new NetJob(QString("JRE::QueryAzulMeta"), APPLICATION->network()); + downloadJob->addNetAction(Net::Download::makeByteArray(QString( + "https://api.azul.com/zulu/download/community/v1.0/bundles/?" + "java_version=%1" + "&os=%2" + "&arch=%3" + "&hw_bitness=%4" + "&ext=zip" //as a zip for all os, even linux + "&bundle_type=jre" //jre only + "&latest=true" //only get the one latest entry + ).arg(javaVersion,azulOS,arch,bitness), metaResponse)); + QObject::connect(downloadJob, &NetJob::finished,[downloadJob, metaResponse]{ + downloadJob->deleteLater(); + delete metaResponse; + }); + + QObject::connect(downloadJob, &NetJob::succeeded,[metaResponse, isLegacy] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *metaResponse; + return; + } + auto array = doc.array(); + if(!array.empty()){ + //JRE found ! download the zip + auto downloadURL = QUrl(array[0].toObject()["url"].toString()); + auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); + const QString path = downloadURL.host() + '/' + downloadURL.path(); + auto entry = APPLICATION->metacache()->resolveEntry("general", path); + entry->setStale(true); + download->addNetAction(Net::Download::makeCached(downloadURL,entry)); + auto zippath = entry->getFullPath(); + QObject::connect(download, &NetJob::finished,[download]{ + download->deleteLater(); + + }); + QObject::connect(download, &NetJob::succeeded,[isLegacy, zippath]{ + auto output = FS::PathCombine(FS::PathCombine(QCoreApplication::applicationDirPath(), "java"),isLegacy ? "java-legacy" : "java-current"); + //This should do all of the extracting and creating folders + MMCZip::extractDir(zippath, output); + }); + }else{ + qWarning() << "No suitable JRE found !!"; + } + }); + } + }); + + netJob->start(); + +} \ No newline at end of file diff --git a/launcher/JavaDownloader.h b/launcher/JavaDownloader.h new file mode 100644 index 000000000..cc073b54c --- /dev/null +++ b/launcher/JavaDownloader.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace JavaDownloader { + /*Downloads the java to the runtimes folder*/ + void downloadJava(bool isLegacy, const QString& OS); +} From 3433c102b70c1c74c882dd2fa19242725676ffe5 Mon Sep 17 00:00:00 2001 From: timoreo Date: Thu, 30 Jun 2022 18:13:52 +0200 Subject: [PATCH 002/120] Remove old comment and change to piston-meta Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index 43da2df01..f1a24a68c 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -14,10 +14,9 @@ struct File{ }; void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) { - //Query the adoptium API to get a good version auto netJob = new NetJob(QString("JRE::QueryVersions"), APPLICATION->network()); auto response = new QByteArray(); - netJob->addNetAction(Net::Download::makeByteArray(QUrl("https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); + netJob->addNetAction(Net::Download::makeByteArray(QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); QObject::connect(netJob, &NetJob::finished,[netJob, response]{ netJob->deleteLater(); delete response; From 9a4a92de4f90334a9dcf1b7b7712f628b232d480 Mon Sep 17 00:00:00 2001 From: timoreo Date: Fri, 1 Jul 2022 08:52:56 +0200 Subject: [PATCH 003/120] Clang format Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 124 +++++++++++++++++------------------- launcher/JavaDownloader.h | 6 +- 2 files changed, 63 insertions(+), 67 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index f1a24a68c..5c3d04a6d 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -1,158 +1,155 @@ #include "JavaDownloader.h" -#include "net/NetJob.h" #include "Application.h" #include "FileSystem.h" -#include "quazip.h" #include "MMCZip.h" #include "net/ChecksumValidator.h" +#include "net/NetJob.h" +#include "quazip.h" -//Quick & dirty struct to store files -struct File{ +// Quick & dirty struct to store files +struct File { QString path; QString url; QByteArray hash; }; -void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) { +void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) +{ auto netJob = new NetJob(QString("JRE::QueryVersions"), APPLICATION->network()); auto response = new QByteArray(); - netJob->addNetAction(Net::Download::makeByteArray(QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); - QObject::connect(netJob, &NetJob::finished,[netJob, response]{ + netJob->addNetAction(Net::Download::makeByteArray( + QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); + QObject::connect(netJob, &NetJob::finished, [netJob, response] { netJob->deleteLater(); delete response; }); - QObject::connect(netJob, &NetJob::succeeded,[response, &OS, isLegacy] { + QObject::connect(netJob, &NetJob::succeeded, [response, &OS, isLegacy] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset - << " reason: " << parse_error.errorString(); + qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << *response; return; } auto versionArray = doc.object()[OS].toObject()[isLegacy ? "jre-legacy" : "java-runtime-gamma"].toArray(); - if(!versionArray.empty()){ + if (!versionArray.empty()) { auto url = versionArray[0].toObject()["manifest"].toObject()["url"].toString(); auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); auto files = new QByteArray(); download->addNetAction(Net::Download::makeByteArray(QUrl(url), files)); - QObject::connect(download, &NetJob::finished,[download, files]{ + QObject::connect(download, &NetJob::finished, [download, files] { download->deleteLater(); delete files; }); - QObject::connect(download, &NetJob::succeeded,[files, isLegacy] { + QObject::connect(download, &NetJob::succeeded, [files, isLegacy] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset - << " reason: " << parse_error.errorString(); + qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << *files; return; } - //valid json doc, begin making jre spot - auto output = FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java/") + (isLegacy ? "java-legacy" : "java-current")); + // valid json doc, begin making jre spot + auto output = + FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java/") + (isLegacy ? "java-legacy" : "java-current")); FS::ensureFolderPathExists(output); std::vector toDownload; auto list = doc.object()["files"].toObject(); - for(auto element : list){ + for (auto element : list) { auto obj = element.toObject(); - for(const auto& paths : obj.keys()){ - auto file = FS::PathCombine(output,paths); + for (const auto& paths : obj.keys()) { + auto file = FS::PathCombine(output, paths); auto type = obj[paths].toObject()["type"].toString(); - if(type == "directory"){ + if (type == "directory") { FS::ensureFolderPathExists(file); - }else if(type == "link"){ - //this is linux only ! - auto target = FS::PathCombine(file,"../"+obj[paths].toObject()["target"].toString()); + } else if (type == "link") { + // this is linux only ! + auto target = FS::PathCombine(file, "../" + obj[paths].toObject()["target"].toString()); QFile(target).link(file); - }else if(type == "file"){ - //TODO download compressed version if it exists ? + } else if (type == "file") { + // TODO download compressed version if it exists ? auto raw = obj[paths].toObject()["downloads"].toObject()["raw"].toObject(); - auto f = File{file,raw["url"].toString(), QByteArray::fromHex(raw["sha1"].toString().toLatin1())}; + auto f = File{ file, raw["url"].toString(), QByteArray::fromHex(raw["sha1"].toString().toLatin1()) }; toDownload.push_back(f); } } } auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network()); - for(const auto& file : toDownload){ - auto dl = Net::Download::makeFile(file.url,file.path); + for (const auto& file : toDownload) { + auto dl = Net::Download::makeFile(file.url, file.path); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash)); elementDownload->addNetAction(dl); } - QObject::connect(elementDownload, &NetJob::finished,[elementDownload]{ - elementDownload->deleteLater(); - }); + QObject::connect(elementDownload, &NetJob::finished, [elementDownload] { elementDownload->deleteLater(); }); elementDownload->start(); }); download->start(); - }else{ - //mojang does not have a JRE for us, let's get azul zulu + } else { + // mojang does not have a JRE for us, let's get azul zulu QString javaVersion = isLegacy ? QString("8.0") : QString("17.0"); QString azulOS; QString arch; QString bitness; - if(OS == "mac-os-arm64"){ - //macos arm64 + if (OS == "mac-os-arm64") { + // macos arm64 azulOS = "macos"; arch = "arm"; bitness = "64"; - }else if(OS == "linux-aarch64"){ - //linux aarch64 + } else if (OS == "linux-aarch64") { + // linux aarch64 azulOS = "linux"; arch = "arm"; bitness = "64"; } auto metaResponse = new QByteArray(); auto downloadJob = new NetJob(QString("JRE::QueryAzulMeta"), APPLICATION->network()); - downloadJob->addNetAction(Net::Download::makeByteArray(QString( - "https://api.azul.com/zulu/download/community/v1.0/bundles/?" - "java_version=%1" - "&os=%2" - "&arch=%3" - "&hw_bitness=%4" - "&ext=zip" //as a zip for all os, even linux - "&bundle_type=jre" //jre only - "&latest=true" //only get the one latest entry - ).arg(javaVersion,azulOS,arch,bitness), metaResponse)); - QObject::connect(downloadJob, &NetJob::finished,[downloadJob, metaResponse]{ + downloadJob->addNetAction(Net::Download::makeByteArray(QString("https://api.azul.com/zulu/download/community/v1.0/bundles/?" + "java_version=%1" + "&os=%2" + "&arch=%3" + "&hw_bitness=%4" + "&ext=zip" // as a zip for all os, even linux + "&bundle_type=jre" // jre only + "&latest=true" // only get the one latest entry + ) + .arg(javaVersion, azulOS, arch, bitness), + metaResponse)); + QObject::connect(downloadJob, &NetJob::finished, [downloadJob, metaResponse] { downloadJob->deleteLater(); delete metaResponse; }); - QObject::connect(downloadJob, &NetJob::succeeded,[metaResponse, isLegacy] { + QObject::connect(downloadJob, &NetJob::succeeded, [metaResponse, isLegacy] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset - << " reason: " << parse_error.errorString(); + qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << *metaResponse; return; } auto array = doc.array(); - if(!array.empty()){ - //JRE found ! download the zip + if (!array.empty()) { + // JRE found ! download the zip auto downloadURL = QUrl(array[0].toObject()["url"].toString()); auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); const QString path = downloadURL.host() + '/' + downloadURL.path(); auto entry = APPLICATION->metacache()->resolveEntry("general", path); entry->setStale(true); - download->addNetAction(Net::Download::makeCached(downloadURL,entry)); + download->addNetAction(Net::Download::makeCached(downloadURL, entry)); auto zippath = entry->getFullPath(); - QObject::connect(download, &NetJob::finished,[download]{ - download->deleteLater(); - - }); - QObject::connect(download, &NetJob::succeeded,[isLegacy, zippath]{ - auto output = FS::PathCombine(FS::PathCombine(QCoreApplication::applicationDirPath(), "java"),isLegacy ? "java-legacy" : "java-current"); - //This should do all of the extracting and creating folders + QObject::connect(download, &NetJob::finished, [download] { download->deleteLater(); }); + QObject::connect(download, &NetJob::succeeded, [isLegacy, zippath] { + auto output = FS::PathCombine(FS::PathCombine(QCoreApplication::applicationDirPath(), "java"), + isLegacy ? "java-legacy" : "java-current"); + // This should do all of the extracting and creating folders MMCZip::extractDir(zippath, output); }); - }else{ + } else { qWarning() << "No suitable JRE found !!"; } }); @@ -160,5 +157,4 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) { }); netJob->start(); - } \ No newline at end of file diff --git a/launcher/JavaDownloader.h b/launcher/JavaDownloader.h index cc073b54c..3dd57eebe 100644 --- a/launcher/JavaDownloader.h +++ b/launcher/JavaDownloader.h @@ -3,6 +3,6 @@ #include namespace JavaDownloader { - /*Downloads the java to the runtimes folder*/ - void downloadJava(bool isLegacy, const QString& OS); -} +/*Downloads the java to the runtimes folder*/ +void downloadJava(bool isLegacy, const QString& OS); +} // namespace JavaDownloader From a97387b692456cae3b13b48ea9e5901712334f4c Mon Sep 17 00:00:00 2001 From: timoreo Date: Fri, 1 Jul 2022 09:37:23 +0200 Subject: [PATCH 004/120] Cherry-pick SysInfo from #680 Signed-off-by: timoreo --- launcher/CMakeLists.txt | 2 + launcher/SysInfo.cpp | 155 ++++++++++++++++++++++++++++++++++++++++ launcher/SysInfo.h | 13 ++++ 3 files changed, 170 insertions(+) create mode 100644 launcher/SysInfo.cpp create mode 100644 launcher/SysInfo.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 4e5508579..c4d9cb74f 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -580,6 +580,8 @@ SET(LAUNCHER_SOURCES UpdateController.h ApplicationMessage.h ApplicationMessage.cpp + SysInfo.h + SysInfo.cpp # GUI - general utilities DesktopServices.h diff --git a/launcher/SysInfo.cpp b/launcher/SysInfo.cpp new file mode 100644 index 000000000..4abf39301 --- /dev/null +++ b/launcher/SysInfo.cpp @@ -0,0 +1,155 @@ +#include +#include +#include "settings/SettingsObject.h" +#ifdef Q_OS_MACOS +#include +#endif +#include +#include +#include +#include "MessageLevel.h" +#include +#include +#include +#include "java/JavaUtils.h" +#include "FileSystem.h" +#include "Commandline.h" +#include "Application.h" + +#ifdef Q_OS_MACOS +bool rosettaDetect() { + int ret = 0; + size_t size = sizeof(ret); + if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) + { + return false; + } + if(ret == 0) + { + return false; + } + if(ret == 1) + { + return true; + } + return false; +} +#endif + +namespace SysInfo { +QString currentSystem() { +#if defined(Q_OS_LINUX) + return "linux"; +#elif defined(Q_OS_MACOS) + return "osx"; +#elif defined(Q_OS_WINDOWS) + return "windows"; +#elif defined(Q_OS_FREEBSD) + return "freebsd"; +#elif defined(Q_OS_OPENBSD) + return "openbsd"; +#else + return "unknown"; +#endif +} + +QString useQTForArch(){ + auto qtArch = QSysInfo::currentCpuArchitecture(); +#if defined(Q_OS_MACOS) && !defined(Q_PROCESSOR_ARM) + if(rosettaDetect()) + { + return "arm64"; + } + else + { + return "x86_64"; + } +#endif + return qtArch; +} + +QString runCheckerForArch(const SettingsObjectPtr& settingsObj){ + QString checkerJar = FS::PathCombine(APPLICATION->getJarsPath(), "JavaCheck.jar"); + + QStringList args; + + QProcessPtr process = new QProcess(); + args.append({"-jar", checkerJar}); + process->setArguments(args); + process->setProgram(settingsObj->get("JavaPath").toString()); + process->setProcessChannelMode(QProcess::SeparateChannels); + process->setProcessEnvironment(CleanEnviroment()); + qDebug() << "Running java checker: " + settingsObj->get("JavaPath").toString() + args.join(" ");; + + process->start(); + if(!process->waitForFinished(15000)){ + // we've been waiting for 15 seconds! wtf! OR... it already finished. But HOW WOULD THAT HAPPEN? + process->kill(); // die. BUUURNNNN + // fallback to using polymc arch + return useQTForArch(); + } else { + // yay we can use the java arch + QString stdout_javaChecker; + QString stderr_javaChecker; + + // process stdout + QByteArray data = process->readAllStandardOutput(); + QString added = QString::fromLocal8Bit(data); + added.remove('\r'); + stdout_javaChecker += added; + + // process stderr + data = process->readAllStandardError(); + added = QString::fromLocal8Bit(data); + added.remove('\r'); + stderr_javaChecker += added; + + QMap results; + QStringList lines = stdout_javaChecker.split("\n", QString::SkipEmptyParts); + for(QString line : lines) + { + line = line.trimmed(); + // NOTE: workaround for GH-4125, where garbage is getting printed into stdout on bedrock linux + if (line.contains("/bedrock/strata")) { + continue; + } + + auto parts = line.split('=', QString::SkipEmptyParts); + if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty()) + { + continue; + } + else + { + results.insert(parts[0], parts[1]); + } + } + + if(!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor")) + { + // wtf man why + // fallback to using polymc arch + return useQTForArch(); + } + + return results["os.arch"]; + } +} + +QString currentArch(const SettingsObjectPtr& settingsObj) { + auto realJavaArchitecture = settingsObj->get("JavaRealArchitecture").toString(); + if(realJavaArchitecture == ""){ + //BRO WHY NOW I HAVE TO USE A JAVA CHECKER >:( + qDebug() << "SysInfo: BRO I HAVE TO USE A JAVA CHECKER WHY IS JAVA ARCH BORKED"; + settingsObj->set("JavaRealArchitecture", runCheckerForArch(settingsObj)); + realJavaArchitecture = settingsObj->get("JavaRealArchitecture").toString(); + } + //qDebug() << "SysInfo: realJavaArch = " << realJavaArchitecture; + if(realJavaArchitecture == "aarch64"){ + return "arm64"; + } else { + return realJavaArchitecture; + } +} +} + diff --git a/launcher/SysInfo.h b/launcher/SysInfo.h new file mode 100644 index 000000000..a4e41e674 --- /dev/null +++ b/launcher/SysInfo.h @@ -0,0 +1,13 @@ +#include +#include "settings/SettingsObject.h" +#ifdef Q_OS_MACOS +#include +#endif + +namespace SysInfo { +QString currentSystem(); +QString currentArch(const SettingsObjectPtr& settingsObj); +QString runCheckerForArch(const SettingsObjectPtr& settingsObj); +QString useQTForArch(); +} + From 98a82cd4847160f41e728403efee51ebc4d2b60a Mon Sep 17 00:00:00 2001 From: timoreo Date: Fri, 1 Jul 2022 14:03:45 +0200 Subject: [PATCH 005/120] Fix MMCZip bugs Signed-off-by: timoreo --- launcher/MMCZip.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 9f4e968f7..3b5c44425 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -300,6 +300,11 @@ std::optional MMCZip::extractSubDir(QuaZip *zip, const QString & su name.remove(0, subdir.size()); auto original_name = name; + // Fix subdirs/files ending with a / getting transformed into absolute paths + if(name.startsWith('/')){ + name = name.mid(1); + } + // Fix weird "folders with a single file get squashed" thing QString path; if(name.contains('/') && !name.endsWith('/')){ @@ -319,6 +324,11 @@ std::optional MMCZip::extractSubDir(QuaZip *zip, const QString & su absFilePath = directory.absoluteFilePath(path + name); } + //Block potential file traversal issues + if(!absFilePath.startsWith(directory.absolutePath())){ + qWarning() << "Potential file traversal issue, for path " << absFilePath << " with base name as " << directory.absolutePath(); + continue; + } if (!JlCompress::extractFile(zip, "", absFilePath)) { qWarning() << "Failed to extract file" << original_name << "to" << absFilePath; From 89ce80b27960e66efccfaee20b3baf1596a8ba53 Mon Sep 17 00:00:00 2001 From: timoreo Date: Fri, 1 Jul 2022 14:05:14 +0200 Subject: [PATCH 006/120] Fix Java downloader bugs + Add a test button in JavaPage Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 63 ++++++++++++++++----------- launcher/ui/pages/global/JavaPage.cpp | 41 +++++++++++++++++ launcher/ui/pages/global/JavaPage.h | 1 + launcher/ui/pages/global/JavaPage.ui | 11 ++++- 4 files changed, 88 insertions(+), 28 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index 5c3d04a6d..3af69f025 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -1,6 +1,7 @@ #include "JavaDownloader.h" #include "Application.h" #include "FileSystem.h" +#include "Json.h" #include "MMCZip.h" #include "net/ChecksumValidator.h" #include "net/NetJob.h" @@ -11,6 +12,7 @@ struct File { QString path; QString url; QByteArray hash; + bool isExec; }; void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) @@ -23,7 +25,7 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) netJob->deleteLater(); delete response; }); - QObject::connect(netJob, &NetJob::succeeded, [response, &OS, isLegacy] { + QObject::connect(netJob, &NetJob::succeeded, [response, OS, isLegacy] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -31,7 +33,7 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) qWarning() << *response; return; } - auto versionArray = doc.object()[OS].toObject()[isLegacy ? "jre-legacy" : "java-runtime-gamma"].toArray(); + auto versionArray = Json::ensureArray(Json::ensureObject(doc.object(), OS), isLegacy ? "jre-legacy" : "java-runtime-gamma"); if (!versionArray.empty()) { auto url = versionArray[0].toObject()["manifest"].toObject()["url"].toString(); auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); @@ -53,35 +55,37 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) } // valid json doc, begin making jre spot - auto output = - FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java/") + (isLegacy ? "java-legacy" : "java-current")); + auto output = FS::PathCombine(QString("java"), (isLegacy ? "java-legacy" : "java-current")); FS::ensureFolderPathExists(output); std::vector toDownload; auto list = doc.object()["files"].toObject(); - for (auto element : list) { - auto obj = element.toObject(); - for (const auto& paths : obj.keys()) { - auto file = FS::PathCombine(output, paths); + for (const auto& paths : list.keys()) { + auto file = FS::PathCombine(output, paths); - auto type = obj[paths].toObject()["type"].toString(); - if (type == "directory") { - FS::ensureFolderPathExists(file); - } else if (type == "link") { - // this is linux only ! - auto target = FS::PathCombine(file, "../" + obj[paths].toObject()["target"].toString()); - QFile(target).link(file); - } else if (type == "file") { - // TODO download compressed version if it exists ? - auto raw = obj[paths].toObject()["downloads"].toObject()["raw"].toObject(); - auto f = File{ file, raw["url"].toString(), QByteArray::fromHex(raw["sha1"].toString().toLatin1()) }; - toDownload.push_back(f); - } + auto type = list[paths].toObject()["type"].toString(); + if (type == "directory") { + FS::ensureFolderPathExists(file); + } else if (type == "link") { + // this is linux only ! + auto target = FS::PathCombine(file, "../" + list[paths].toObject()["target"].toString()); + QFile(target).link(file); + } else if (type == "file") { + // TODO download compressed version if it exists ? + auto raw = list[paths].toObject()["downloads"].toObject()["raw"].toObject(); + auto isExec = list[paths].toObject()["executable"].toBool(); + auto f = File{ file, raw["url"].toString(), QByteArray::fromHex(raw["sha1"].toString().toLatin1()), isExec }; + toDownload.push_back(f); } } auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network()); for (const auto& file : toDownload) { auto dl = Net::Download::makeFile(file.url, file.path); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash)); + if (file.isExec) { + QObject::connect(dl.get(), &Net::Download::succeeded, [file] { + QFile(file.path).setPermissions(QFile(file.path).permissions() | QFileDevice::Permissions(0x1111)); + }); + } elementDownload->addNetAction(dl); } QObject::connect(elementDownload, &NetJob::finished, [elementDownload] { elementDownload->deleteLater(); }); @@ -90,7 +94,7 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) download->start(); } else { // mojang does not have a JRE for us, let's get azul zulu - QString javaVersion = isLegacy ? QString("8.0") : QString("17.0"); + QString javaVersion = isLegacy ? QString("8.0") : QString("18.0"); QString azulOS; QString arch; QString bitness; @@ -100,11 +104,16 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) azulOS = "macos"; arch = "arm"; bitness = "64"; - } else if (OS == "linux-aarch64") { - // linux aarch64 + } else if (OS == "linux-arm64") { + // linux arm64 azulOS = "linux"; arch = "arm"; bitness = "64"; + } else if (OS == "linux-arm") { + // linux arm (32) + azulOS = "linux"; + arch = "arm"; + bitness = "32"; } auto metaResponse = new QByteArray(); auto downloadJob = new NetJob(QString("JRE::QueryAzulMeta"), APPLICATION->network()); @@ -143,16 +152,18 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) download->addNetAction(Net::Download::makeCached(downloadURL, entry)); auto zippath = entry->getFullPath(); QObject::connect(download, &NetJob::finished, [download] { download->deleteLater(); }); - QObject::connect(download, &NetJob::succeeded, [isLegacy, zippath] { + QObject::connect(download, &NetJob::succeeded, [isLegacy, zippath, downloadURL] { auto output = FS::PathCombine(FS::PathCombine(QCoreApplication::applicationDirPath(), "java"), isLegacy ? "java-legacy" : "java-current"); // This should do all of the extracting and creating folders - MMCZip::extractDir(zippath, output); + MMCZip::extractDir(zippath, downloadURL.fileName().chopped(4), output); }); + download->start(); } else { qWarning() << "No suitable JRE found !!"; } }); + downloadJob->start(); } }); diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 2cee15bf1..a57a8ee06 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -52,6 +52,9 @@ #include #include "Application.h" #include +#include "SysInfo.h" +#include "JavaDownloader.h" + JavaPage::JavaPage(QWidget *parent) : QWidget(parent), ui(new Ui::JavaPage) { @@ -177,6 +180,44 @@ void JavaPage::on_javaTestBtn_clicked() checker->run(); } +void JavaPage::on_javaDownloadBtn_clicked(){ + QString sys = SysInfo::currentSystem(); + if(sys == "osx"){ + sys = "mac-os"; + } + QString arch = SysInfo::useQTForArch(); + QString version; + if(sys == "windows"){ + if(arch == "x86_64"){ + version = "windows-x64"; + }else if(arch == "i386"){ + version = "windows-x86"; + }else{ + //Unknown, maybe arm, appending arch for downloader + version = "windows-"+arch; + } + }else if(sys == "mac-os"){ + if(arch == "arm64"){ + version = "mac-os-arm64"; + }else{ + version = "mac-os"; + } + }else if(sys == "linux"){ + if(arch == "x86_64"){ + version = "linux"; + }else { + // will work for i386, and arm(64) + version = "linux-" + arch; + } + }else{ + // ? ? ? ? ? unknown os, at least it won't have a java version on mojang or azul, display warning + QMessageBox::warning(this, tr("Unknown OS"), tr("The OS you are running is not supported by Mojang or Azul. Please install Java manually.")); + return; + } + //TODO display a selection for java 8 or 18 + JavaDownloader::downloadJava(false, version); +} + void JavaPage::checkerFinished() { checker.reset(); diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h index 64d4098e5..aa06dc0be 100644 --- a/launcher/ui/pages/global/JavaPage.h +++ b/launcher/ui/pages/global/JavaPage.h @@ -85,6 +85,7 @@ slots: void on_javaDetectBtn_clicked(); void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); + void on_javaDownloadBtn_clicked(); void checkerFinished(); private: diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index 6ccffed4d..c109efbfc 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -6,8 +6,8 @@ 0 0 - 545 - 580 + 559 + 659 @@ -279,6 +279,13 @@ + + + + Download Java + + + From 54ad91c3b79dbd3379e6f0e1c7bc76f149fc6794 Mon Sep 17 00:00:00 2001 From: timoreo Date: Fri, 1 Jul 2022 14:18:34 +0200 Subject: [PATCH 007/120] Anti-scrumped Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index 3af69f025..09aeed5de 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -168,4 +168,4 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) }); netJob->start(); -} \ No newline at end of file +} From 53ddba80778e7c232cd778c1eabc0bc36c3f6414 Mon Sep 17 00:00:00 2001 From: timoreo Date: Sun, 10 Jul 2022 19:56:52 +0200 Subject: [PATCH 008/120] Made JavaDownloader a task and added some quick UI Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 51 +++++++++++++++++---------- launcher/JavaDownloader.h | 17 ++++++--- launcher/ui/pages/global/JavaPage.cpp | 28 +++++++++++---- 3 files changed, 67 insertions(+), 29 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index 09aeed5de..d72f66f36 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -15,17 +15,21 @@ struct File { bool isExec; }; -void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) +void JavaDownloader::executeTask() { + auto OS = m_OS; + auto isLegacy = m_isLegacy; auto netJob = new NetJob(QString("JRE::QueryVersions"), APPLICATION->network()); auto response = new QByteArray(); + setStatus(tr("Querying mojang meta")); netJob->addNetAction(Net::Download::makeByteArray( QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); QObject::connect(netJob, &NetJob::finished, [netJob, response] { netJob->deleteLater(); delete response; }); - QObject::connect(netJob, &NetJob::succeeded, [response, OS, isLegacy] { + QObject::connect(netJob, &NetJob::progress, this, &JavaDownloader::progress); + QObject::connect(netJob, &NetJob::succeeded, [response, OS, isLegacy, this] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -35,6 +39,7 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) } auto versionArray = Json::ensureArray(Json::ensureObject(doc.object(), OS), isLegacy ? "jre-legacy" : "java-runtime-gamma"); if (!versionArray.empty()) { + setStatus(tr("Downloading java from Mojang")); auto url = versionArray[0].toObject()["manifest"].toObject()["url"].toString(); auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); auto files = new QByteArray(); @@ -45,7 +50,8 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) download->deleteLater(); delete files; }); - QObject::connect(download, &NetJob::succeeded, [files, isLegacy] { + QObject::connect(download, &NetJob::progress, this, &JavaDownloader::progress); + QObject::connect(download, &NetJob::succeeded, [files, isLegacy, this] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -89,12 +95,14 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) elementDownload->addNetAction(dl); } QObject::connect(elementDownload, &NetJob::finished, [elementDownload] { elementDownload->deleteLater(); }); + QObject::connect(elementDownload, &NetJob::succeeded, [this]{emitSucceeded();}); elementDownload->start(); }); download->start(); } else { // mojang does not have a JRE for us, let's get azul zulu - QString javaVersion = isLegacy ? QString("8.0") : QString("18.0"); + setStatus(tr("Querying Azul meta")); + QString javaVersion = isLegacy ? QString("8.0") : QString("17.0"); QString azulOS; QString arch; QString bitness; @@ -117,23 +125,24 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) } auto metaResponse = new QByteArray(); auto downloadJob = new NetJob(QString("JRE::QueryAzulMeta"), APPLICATION->network()); - downloadJob->addNetAction(Net::Download::makeByteArray(QString("https://api.azul.com/zulu/download/community/v1.0/bundles/?" - "java_version=%1" - "&os=%2" - "&arch=%3" - "&hw_bitness=%4" - "&ext=zip" // as a zip for all os, even linux - "&bundle_type=jre" // jre only - "&latest=true" // only get the one latest entry - ) - .arg(javaVersion, azulOS, arch, bitness), - metaResponse)); + downloadJob->addNetAction( + Net::Download::makeByteArray(QString("https://api.azul.com/zulu/download/community/v1.0/bundles/?" + "java_version=%1" + "&os=%2" + "&arch=%3" + "&hw_bitness=%4" + "&ext=zip" // as a zip for all os, even linux NOTE !! Linux ARM is .deb only !! + "&bundle_type=jre" // jre only + "&latest=true" // only get the one latest entry + ) + .arg(javaVersion, azulOS, arch, bitness), + metaResponse)); QObject::connect(downloadJob, &NetJob::finished, [downloadJob, metaResponse] { downloadJob->deleteLater(); delete metaResponse; }); - - QObject::connect(downloadJob, &NetJob::succeeded, [metaResponse, isLegacy] { + QObject::connect(downloadJob, &NetJob::progress, this, &JavaDownloader::progress); + QObject::connect(downloadJob, &NetJob::succeeded, [metaResponse, isLegacy, this] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -144,6 +153,7 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) auto array = doc.array(); if (!array.empty()) { // JRE found ! download the zip + setStatus(tr("Downloading java from Azul")); auto downloadURL = QUrl(array[0].toObject()["url"].toString()); auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); const QString path = downloadURL.host() + '/' + downloadURL.path(); @@ -152,15 +162,18 @@ void JavaDownloader::downloadJava(bool isLegacy, const QString& OS) download->addNetAction(Net::Download::makeCached(downloadURL, entry)); auto zippath = entry->getFullPath(); QObject::connect(download, &NetJob::finished, [download] { download->deleteLater(); }); - QObject::connect(download, &NetJob::succeeded, [isLegacy, zippath, downloadURL] { + QObject::connect(download, &NetJob::progress, this, &JavaDownloader::progress); + QObject::connect(download, &NetJob::succeeded, [isLegacy, zippath, downloadURL, this] { + setStatus(tr("Extracting java")); auto output = FS::PathCombine(FS::PathCombine(QCoreApplication::applicationDirPath(), "java"), isLegacy ? "java-legacy" : "java-current"); // This should do all of the extracting and creating folders MMCZip::extractDir(zippath, downloadURL.fileName().chopped(4), output); + emitSucceeded(); }); download->start(); } else { - qWarning() << "No suitable JRE found !!"; + emitFailed(tr("No suitable JRE found")); } }); downloadJob->start(); diff --git a/launcher/JavaDownloader.h b/launcher/JavaDownloader.h index 3dd57eebe..3b7a7c425 100644 --- a/launcher/JavaDownloader.h +++ b/launcher/JavaDownloader.h @@ -1,8 +1,17 @@ #pragma once #include +#include "tasks/Task.h" -namespace JavaDownloader { -/*Downloads the java to the runtimes folder*/ -void downloadJava(bool isLegacy, const QString& OS); -} // namespace JavaDownloader +class JavaDownloader : public Task { + Q_OBJECT + public: + /*Downloads the java to the runtimes folder*/ + explicit JavaDownloader(bool isLegacy, const QString& OS) : m_isLegacy(isLegacy), m_OS(OS) {} + + void executeTask() override; + + private: + bool m_isLegacy; + const QString& m_OS; +}; diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index a57a8ee06..2cc627b7d 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -48,13 +48,14 @@ #include "java/JavaUtils.h" #include "java/JavaInstallList.h" -#include "settings/SettingsObject.h" #include -#include "Application.h" #include -#include "SysInfo.h" +#include "Application.h" #include "JavaDownloader.h" - +#include "SysInfo.h" +#include "settings/SettingsObject.h" +#include "ui/dialogs/ProgressDialog.h" +#include JavaPage::JavaPage(QWidget *parent) : QWidget(parent), ui(new Ui::JavaPage) { @@ -214,8 +215,23 @@ void JavaPage::on_javaDownloadBtn_clicked(){ QMessageBox::warning(this, tr("Unknown OS"), tr("The OS you are running is not supported by Mojang or Azul. Please install Java manually.")); return; } - //TODO display a selection for java 8 or 18 - JavaDownloader::downloadJava(false, version); + //Selection using QMessageBox for java 8 or 17 + QMessageBox box(QMessageBox::Icon::Question, tr("Java version"), tr("Do you want to download Java version 8 or 17?\n Java 8 is recommended for minecraft versions below 1.17\n Java 17 is recommended for minecraft versions above or equal to 1.17"), + QMessageBox::NoButton, this); + box.addButton("Java 17", QMessageBox::YesRole); + auto no = box.addButton("Java 8", QMessageBox::NoRole); + auto cancel = box.addButton(tr("Download both"), QMessageBox::AcceptRole); + box.exec(); + bool isLegacy = box.clickedButton() == no; + + auto down = new JavaDownloader(isLegacy, version); + ProgressDialog dialog(this); + dialog.execWithTask(down); + if(box.clickedButton() == cancel) { + auto dwn = new JavaDownloader(false, version); + ProgressDialog dg(this); + dg.execWithTask(dwn); + } } void JavaPage::checkerFinished() From f946964490c181700cbc0b1b479fd6089f4ba02e Mon Sep 17 00:00:00 2001 From: timoreo Date: Sun, 10 Jul 2022 20:21:52 +0200 Subject: [PATCH 009/120] Regrab a few changes on SysInfo Signed-off-by: timoreo --- launcher/CMakeLists.txt | 2 ++ launcher/SysInfo.cpp | 32 ++++++++++++++++------- launcher/SysInfo.h | 9 +++---- launcher/minecraft/LaunchContext.cpp | 39 ++++++++++++++++++++++++++++ launcher/minecraft/LaunchContext.h | 34 ++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 launcher/minecraft/LaunchContext.cpp create mode 100644 launcher/minecraft/LaunchContext.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index c4d9cb74f..c467957a8 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -271,6 +271,8 @@ set(MINECRAFT_SOURCES minecraft/GradleSpecifier.h minecraft/MinecraftInstance.cpp minecraft/MinecraftInstance.h + minecraft/LaunchContext.cpp + minecraft/LaunchContext.h minecraft/LaunchProfile.cpp minecraft/LaunchProfile.h minecraft/Component.cpp diff --git a/launcher/SysInfo.cpp b/launcher/SysInfo.cpp index 4abf39301..010eb84c8 100644 --- a/launcher/SysInfo.cpp +++ b/launcher/SysInfo.cpp @@ -1,6 +1,6 @@ #include #include -#include "settings/SettingsObject.h" +#include "minecraft/LaunchContext.h" #ifdef Q_OS_MACOS #include #endif @@ -68,18 +68,24 @@ QString useQTForArch(){ return qtArch; } -QString runCheckerForArch(const SettingsObjectPtr& settingsObj){ - QString checkerJar = FS::PathCombine(APPLICATION->getJarsPath(), "JavaCheck.jar"); +QString runCheckerForArch(LaunchContext launchContext){ + QString checkerJar = JavaUtils::getJavaCheckPath(); + + if (checkerJar.isEmpty()) + { + qDebug() << "Java checker library could not be found. Please check your installation."; + return useQTForArch(); + } QStringList args; QProcessPtr process = new QProcess(); args.append({"-jar", checkerJar}); process->setArguments(args); - process->setProgram(settingsObj->get("JavaPath").toString()); + process->setProgram(launchContext.getJavaPath().toString()); process->setProcessChannelMode(QProcess::SeparateChannels); process->setProcessEnvironment(CleanEnviroment()); - qDebug() << "Running java checker: " + settingsObj->get("JavaPath").toString() + args.join(" ");; + qDebug() << "Running java checker: " + launchContext.getJavaPath().toString() + args.join(" ");; process->start(); if(!process->waitForFinished(15000)){ @@ -105,7 +111,11 @@ QString runCheckerForArch(const SettingsObjectPtr& settingsObj){ stderr_javaChecker += added; QMap results; +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QStringList lines = stdout_javaChecker.split("\n", Qt::SkipEmptyParts); +#else QStringList lines = stdout_javaChecker.split("\n", QString::SkipEmptyParts); +#endif for(QString line : lines) { line = line.trimmed(); @@ -114,7 +124,11 @@ QString runCheckerForArch(const SettingsObjectPtr& settingsObj){ continue; } +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + auto parts = line.split('=', Qt::SkipEmptyParts); +#else auto parts = line.split('=', QString::SkipEmptyParts); +#endif if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty()) { continue; @@ -136,13 +150,13 @@ QString runCheckerForArch(const SettingsObjectPtr& settingsObj){ } } -QString currentArch(const SettingsObjectPtr& settingsObj) { - auto realJavaArchitecture = settingsObj->get("JavaRealArchitecture").toString(); +QString currentArch(LaunchContext launchContext) { + auto realJavaArchitecture = launchContext.getRealJavaArch().toString(); if(realJavaArchitecture == ""){ //BRO WHY NOW I HAVE TO USE A JAVA CHECKER >:( qDebug() << "SysInfo: BRO I HAVE TO USE A JAVA CHECKER WHY IS JAVA ARCH BORKED"; - settingsObj->set("JavaRealArchitecture", runCheckerForArch(settingsObj)); - realJavaArchitecture = settingsObj->get("JavaRealArchitecture").toString(); + launchContext.setRealJavaArch(runCheckerForArch(launchContext)); + realJavaArchitecture = launchContext.getRealJavaArch().toString(); } //qDebug() << "SysInfo: realJavaArch = " << realJavaArchitecture; if(realJavaArchitecture == "aarch64"){ diff --git a/launcher/SysInfo.h b/launcher/SysInfo.h index a4e41e674..280757674 100644 --- a/launcher/SysInfo.h +++ b/launcher/SysInfo.h @@ -1,13 +1,12 @@ #include -#include "settings/SettingsObject.h" +#include "minecraft/LaunchContext.h" #ifdef Q_OS_MACOS #include #endif namespace SysInfo { QString currentSystem(); -QString currentArch(const SettingsObjectPtr& settingsObj); -QString runCheckerForArch(const SettingsObjectPtr& settingsObj); +QString currentArch(LaunchContext launchContext); +QString runCheckerForArch(LaunchContext launchContext); QString useQTForArch(); -} - +} \ No newline at end of file diff --git a/launcher/minecraft/LaunchContext.cpp b/launcher/minecraft/LaunchContext.cpp new file mode 100644 index 000000000..b445d9ae1 --- /dev/null +++ b/launcher/minecraft/LaunchContext.cpp @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (C) 2022 Toshit Chawda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "LaunchContext.h" + +LaunchContext::LaunchContext(SettingsObjectPtr instanceSettings){ + m_instanceSettings = instanceSettings; +} + +void LaunchContext::setRealJavaArch(QVariant realJavaArch) +{ + m_instanceSettings->set("JavaRealArchitecture", realJavaArch); +} + +QVariant LaunchContext::getRealJavaArch() +{ + return m_instanceSettings->get("JavaRealArchitecture"); +} + +QVariant LaunchContext::getJavaPath() +{ + return m_instanceSettings->get("JavaPath"); +} \ No newline at end of file diff --git a/launcher/minecraft/LaunchContext.h b/launcher/minecraft/LaunchContext.h new file mode 100644 index 000000000..0d322a2ea --- /dev/null +++ b/launcher/minecraft/LaunchContext.h @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (C) 2022 Toshit Chawda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include "settings/SettingsObject.h" + +#pragma once + +class LaunchContext +{ + public: + LaunchContext(SettingsObjectPtr instanceSettings); + void setRealJavaArch(QVariant realJavaArch); + QVariant getRealJavaArch(); + QVariant getJavaPath(); + private: + SettingsObjectPtr m_instanceSettings; +}; \ No newline at end of file From 68446c2a5442d568a75229d63d6addc502237b4a Mon Sep 17 00:00:00 2001 From: timoreo Date: Sun, 10 Jul 2022 20:34:29 +0200 Subject: [PATCH 010/120] Obligatory formatting fix commit Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 2 +- launcher/SysInfo.h | 2 +- launcher/minecraft/LaunchContext.cpp | 2 +- launcher/minecraft/LaunchContext.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index d72f66f36..2cca83a9b 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -95,7 +95,7 @@ void JavaDownloader::executeTask() elementDownload->addNetAction(dl); } QObject::connect(elementDownload, &NetJob::finished, [elementDownload] { elementDownload->deleteLater(); }); - QObject::connect(elementDownload, &NetJob::succeeded, [this]{emitSucceeded();}); + QObject::connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); elementDownload->start(); }); download->start(); diff --git a/launcher/SysInfo.h b/launcher/SysInfo.h index 280757674..9107cacb8 100644 --- a/launcher/SysInfo.h +++ b/launcher/SysInfo.h @@ -9,4 +9,4 @@ QString currentSystem(); QString currentArch(LaunchContext launchContext); QString runCheckerForArch(LaunchContext launchContext); QString useQTForArch(); -} \ No newline at end of file +} diff --git a/launcher/minecraft/LaunchContext.cpp b/launcher/minecraft/LaunchContext.cpp index b445d9ae1..ea6a549f0 100644 --- a/launcher/minecraft/LaunchContext.cpp +++ b/launcher/minecraft/LaunchContext.cpp @@ -36,4 +36,4 @@ QVariant LaunchContext::getRealJavaArch() QVariant LaunchContext::getJavaPath() { return m_instanceSettings->get("JavaPath"); -} \ No newline at end of file +} diff --git a/launcher/minecraft/LaunchContext.h b/launcher/minecraft/LaunchContext.h index 0d322a2ea..2c6e1307f 100644 --- a/launcher/minecraft/LaunchContext.h +++ b/launcher/minecraft/LaunchContext.h @@ -31,4 +31,4 @@ class LaunchContext QVariant getJavaPath(); private: SettingsObjectPtr m_instanceSettings; -}; \ No newline at end of file +}; From 24dc154856cc45b78404b47fa085f8ea0a1adeb0 Mon Sep 17 00:00:00 2001 From: timoreo Date: Mon, 11 Jul 2022 15:11:08 +0200 Subject: [PATCH 011/120] Add download button to more pages + UI fixes Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 79 +++++++++++++++++++ launcher/JavaDownloader.h | 1 + launcher/ui/pages/global/JavaPage.cpp | 57 +------------ .../pages/instance/InstanceSettingsPage.cpp | 6 ++ .../ui/pages/instance/InstanceSettingsPage.h | 1 + .../ui/pages/instance/InstanceSettingsPage.ui | 7 ++ launcher/ui/widgets/JavaSettingsWidget.cpp | 11 +++ launcher/ui/widgets/JavaSettingsWidget.h | 3 + 8 files changed, 111 insertions(+), 54 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index 2cca83a9b..cb8fd1116 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -1,11 +1,15 @@ #include "JavaDownloader.h" +#include +#include #include "Application.h" #include "FileSystem.h" #include "Json.h" #include "MMCZip.h" +#include "SysInfo.h" #include "net/ChecksumValidator.h" #include "net/NetJob.h" #include "quazip.h" +#include "ui/dialogs/ProgressDialog.h" // Quick & dirty struct to store files struct File { @@ -95,6 +99,7 @@ void JavaDownloader::executeTask() elementDownload->addNetAction(dl); } QObject::connect(elementDownload, &NetJob::finished, [elementDownload] { elementDownload->deleteLater(); }); + QObject::connect(elementDownload, &NetJob::progress, this, &JavaDownloader::progress); QObject::connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); elementDownload->start(); }); @@ -182,3 +187,77 @@ void JavaDownloader::executeTask() netJob->start(); } +void JavaDownloader::showPrompts(QWidget* parent) +{ + QString sys = SysInfo::currentSystem(); + if (sys == "osx") { + sys = "mac-os"; + } + QString arch = SysInfo::useQTForArch(); + QString version; + if (sys == "windows") { + if (arch == "x86_64") { + version = "windows-x64"; + } else if (arch == "i386") { + version = "windows-x86"; + } else { + // Unknown, maybe arm, appending arch for downloader + version = "windows-" + arch; + } + } else if (sys == "mac-os") { + if (arch == "arm64") { + version = "mac-os-arm64"; + } else { + version = "mac-os"; + } + } else if (sys == "linux") { + if (arch == "x86_64") { + version = "linux"; + } else { + // will work for i386, and arm(64) + version = "linux-" + arch; + } + } else { + // ? ? ? ? ? unknown os, at least it won't have a java version on mojang or azul, display warning + QMessageBox::warning(parent, tr("Unknown OS"), + tr("The OS you are running is not supported by Mojang or Azul. Please install Java manually.")); + return; + } + // Selection using QMessageBox for java 8 or 17 + QMessageBox box(QMessageBox::Icon::Question, tr("Java version"), + tr("Do you want to download Java version 8 or 17?\n Java 8 is recommended for minecraft versions below 1.17\n Java 17 " + "is recommended for minecraft versions above or equal to 1.17"), + QMessageBox::NoButton, parent); + auto yes = box.addButton("Java 17", QMessageBox::AcceptRole); + auto no = box.addButton("Java 8", QMessageBox::AcceptRole); + auto both = box.addButton(tr("Download both"), QMessageBox::AcceptRole); + auto cancel = box.addButton(QMessageBox::Cancel); + + if (QFileInfo::exists(FS::PathCombine(QString("java"), "java-legacy"))) { + no->setEnabled(false); + } + if (QFileInfo::exists(FS::PathCombine(QString("java"), "java-current"))) { + yes->setEnabled(false); + } + if (!yes->isEnabled() || !no->isEnabled()) { + both->setEnabled(false); + } + if (!yes->isEnabled() && !no->isEnabled()) { + QMessageBox::warning(parent, tr("Already installed !"), tr("Both versions of java are already installed !")); + return; + } + box.exec(); + if (box.clickedButton() == nullptr || box.clickedButton() == cancel) { + return; + } + bool isLegacy = box.clickedButton() == no; + + auto down = new JavaDownloader(isLegacy, version); + ProgressDialog dialog(parent); + dialog.execWithTask(down); + if (box.clickedButton() == both) { + auto dwn = new JavaDownloader(false, version); + ProgressDialog dg(parent); + dg.execWithTask(dwn); + } +} diff --git a/launcher/JavaDownloader.h b/launcher/JavaDownloader.h index 3b7a7c425..274a95e49 100644 --- a/launcher/JavaDownloader.h +++ b/launcher/JavaDownloader.h @@ -10,6 +10,7 @@ class JavaDownloader : public Task { explicit JavaDownloader(bool isLegacy, const QString& OS) : m_isLegacy(isLegacy), m_OS(OS) {} void executeTask() override; + static void showPrompts(QWidget* parent = nullptr); private: bool m_isLegacy; diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 2cc627b7d..d7f48f552 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -52,10 +52,7 @@ #include #include "Application.h" #include "JavaDownloader.h" -#include "SysInfo.h" #include "settings/SettingsObject.h" -#include "ui/dialogs/ProgressDialog.h" -#include JavaPage::JavaPage(QWidget *parent) : QWidget(parent), ui(new Ui::JavaPage) { @@ -181,57 +178,9 @@ void JavaPage::on_javaTestBtn_clicked() checker->run(); } -void JavaPage::on_javaDownloadBtn_clicked(){ - QString sys = SysInfo::currentSystem(); - if(sys == "osx"){ - sys = "mac-os"; - } - QString arch = SysInfo::useQTForArch(); - QString version; - if(sys == "windows"){ - if(arch == "x86_64"){ - version = "windows-x64"; - }else if(arch == "i386"){ - version = "windows-x86"; - }else{ - //Unknown, maybe arm, appending arch for downloader - version = "windows-"+arch; - } - }else if(sys == "mac-os"){ - if(arch == "arm64"){ - version = "mac-os-arm64"; - }else{ - version = "mac-os"; - } - }else if(sys == "linux"){ - if(arch == "x86_64"){ - version = "linux"; - }else { - // will work for i386, and arm(64) - version = "linux-" + arch; - } - }else{ - // ? ? ? ? ? unknown os, at least it won't have a java version on mojang or azul, display warning - QMessageBox::warning(this, tr("Unknown OS"), tr("The OS you are running is not supported by Mojang or Azul. Please install Java manually.")); - return; - } - //Selection using QMessageBox for java 8 or 17 - QMessageBox box(QMessageBox::Icon::Question, tr("Java version"), tr("Do you want to download Java version 8 or 17?\n Java 8 is recommended for minecraft versions below 1.17\n Java 17 is recommended for minecraft versions above or equal to 1.17"), - QMessageBox::NoButton, this); - box.addButton("Java 17", QMessageBox::YesRole); - auto no = box.addButton("Java 8", QMessageBox::NoRole); - auto cancel = box.addButton(tr("Download both"), QMessageBox::AcceptRole); - box.exec(); - bool isLegacy = box.clickedButton() == no; - - auto down = new JavaDownloader(isLegacy, version); - ProgressDialog dialog(this); - dialog.execWithTask(down); - if(box.clickedButton() == cancel) { - auto dwn = new JavaDownloader(false, version); - ProgressDialog dg(this); - dg.execWithTask(dwn); - } +void JavaPage::on_javaDownloadBtn_clicked() +{ + JavaDownloader::showPrompts(this); } void JavaPage::checkerFinished() diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 5da7f19f5..62e780ce8 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -49,6 +49,7 @@ #include "JavaCommon.h" #include "Application.h" +#include "JavaDownloader.h" #include "java/JavaInstallList.h" #include "java/JavaUtils.h" #include "FileSystem.h" @@ -374,6 +375,11 @@ void InstanceSettingsPage::loadSettings() ui->serverJoinAddress->setText(m_settings->get("JoinServerOnLaunchAddress").toString()); } +void InstanceSettingsPage::on_javaDownloadBtn_clicked() +{ + JavaDownloader::showPrompts(this); +} + void InstanceSettingsPage::on_javaDetectBtn_clicked() { if (JavaUtils::getJavaCheckPath().isEmpty()) { diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 97d1296fe..ffb226781 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -81,6 +81,7 @@ private slots: void on_javaDetectBtn_clicked(); void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); + void on_javaDownloadBtn_clicked(); void applySettings(); void loadSettings(); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 8b3c33702..4ce59a0ae 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -95,6 +95,13 @@ + + + + Download Java... + + + diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 314a126e4..e62cdd1f0 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -14,6 +14,7 @@ #include "JavaCommon.h" #include "java/JavaInstall.h" #include "java/JavaUtils.h" +#include "JavaDownloader.h" #include "FileSystem.h" #include "ui/dialogs/CustomMessageBox.h" @@ -38,6 +39,8 @@ JavaSettingsWidget::JavaSettingsWidget(QWidget* parent) : QWidget(parent) connect(m_javaBrowseBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaBrowseBtn_clicked); connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaSettingsWidget::javaPathEdited); connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaSettingsWidget::on_javaStatusBtn_clicked); + connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaDownloadBtn_clicked); + } void JavaSettingsWidget::setupUi() @@ -115,6 +118,10 @@ void JavaSettingsWidget::setupUi() m_verticalLayout->addWidget(m_memoryGroupBox); + m_javaDownloadBtn = new QPushButton("Download Java",this); + + m_verticalLayout->addWidget(m_javaDownloadBtn); + retranslate(); } @@ -276,7 +283,11 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked() m_javaPathTextBox->setText(cooked_path); checkJavaPath(cooked_path); } +void JavaSettingsWidget::on_javaDownloadBtn_clicked() +{ + JavaDownloader::showPrompts(this); +} void JavaSettingsWidget::on_javaStatusBtn_clicked() { QString text; diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index 0d280daf3..fe6ee2f58 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -63,6 +63,7 @@ protected slots: void javaVersionSelected(BaseVersionPtr version); void on_javaBrowseBtn_clicked(); void on_javaStatusBtn_clicked(); + void on_javaDownloadBtn_clicked(); void checkFinished(JavaCheckResult result); protected: /* methods */ @@ -88,6 +89,8 @@ private: /* data */ QSpinBox *m_minMemSpinBox = nullptr; QLabel *m_labelPermGen = nullptr; QSpinBox *m_permGenSpinBox = nullptr; + + QPushButton *m_javaDownloadBtn = nullptr; QIcon goodIcon; QIcon yellowIcon; QIcon badIcon; From a902f29ccff347f1c51ab95330748cb6e71d1539 Mon Sep 17 00:00:00 2001 From: timoreo Date: Mon, 12 Sep 2022 08:19:42 +0200 Subject: [PATCH 012/120] Changed to a temporary file Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 21 ++++++++++++++------- launcher/ui/widgets/JavaSettingsWidget.cpp | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index cb8fd1116..e56a87d0c 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -1,6 +1,7 @@ #include "JavaDownloader.h" #include #include +#include #include "Application.h" #include "FileSystem.h" #include "Json.h" @@ -127,6 +128,11 @@ void JavaDownloader::executeTask() azulOS = "linux"; arch = "arm"; bitness = "32"; + } else if (OS == "linux"){ + // linux x86 64 (used for debugging, should never reach here) + azulOS = "linux"; + arch = "x86"; + bitness = "64"; } auto metaResponse = new QByteArray(); auto downloadJob = new NetJob(QString("JRE::QueryAzulMeta"), APPLICATION->network()); @@ -161,19 +167,20 @@ void JavaDownloader::executeTask() setStatus(tr("Downloading java from Azul")); auto downloadURL = QUrl(array[0].toObject()["url"].toString()); auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); - const QString path = downloadURL.host() + '/' + downloadURL.path(); - auto entry = APPLICATION->metacache()->resolveEntry("general", path); - entry->setStale(true); - download->addNetAction(Net::Download::makeCached(downloadURL, entry)); - auto zippath = entry->getFullPath(); + auto temp = std::make_unique(FS::PathCombine(APPLICATION->root(), "temp", "XXXXXX.zip")); + FS::ensureFolderPathExists(FS::PathCombine(APPLICATION->root(),"temp")); + // Have to open at least once to generate path + temp->open(); + temp->close(); + download->addNetAction(Net::Download::makeFile(downloadURL, temp->fileName())); QObject::connect(download, &NetJob::finished, [download] { download->deleteLater(); }); QObject::connect(download, &NetJob::progress, this, &JavaDownloader::progress); - QObject::connect(download, &NetJob::succeeded, [isLegacy, zippath, downloadURL, this] { + QObject::connect(download, &NetJob::succeeded, [isLegacy, file = std::move(temp), downloadURL, this] { setStatus(tr("Extracting java")); auto output = FS::PathCombine(FS::PathCombine(QCoreApplication::applicationDirPath(), "java"), isLegacy ? "java-legacy" : "java-current"); // This should do all of the extracting and creating folders - MMCZip::extractDir(zippath, downloadURL.fileName().chopped(4), output); + MMCZip::extractDir(file->fileName(), downloadURL.fileName().chopped(4), output); emitSucceeded(); }); download->start(); diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index e62cdd1f0..6494b79fd 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -118,7 +118,7 @@ void JavaSettingsWidget::setupUi() m_verticalLayout->addWidget(m_memoryGroupBox); - m_javaDownloadBtn = new QPushButton("Download Java",this); + m_javaDownloadBtn = new QPushButton(tr("Download Java"), this); m_verticalLayout->addWidget(m_javaDownloadBtn); From dc84a6199932fed417796ec1183598669b4dde2f Mon Sep 17 00:00:00 2001 From: timoreo Date: Mon, 12 Sep 2022 14:17:41 +0200 Subject: [PATCH 013/120] Added failed and aborted handlers Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 61 +++++++++++++++++++++++++++++++------ launcher/JavaDownloader.h | 3 ++ 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index e56a87d0c..b0cde7d98 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -24,17 +24,29 @@ void JavaDownloader::executeTask() { auto OS = m_OS; auto isLegacy = m_isLegacy; + auto netJob = new NetJob(QString("JRE::QueryVersions"), APPLICATION->network()); auto response = new QByteArray(); setStatus(tr("Querying mojang meta")); netJob->addNetAction(Net::Download::makeByteArray( QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); - QObject::connect(netJob, &NetJob::finished, [netJob, response] { + + QObject::connect(this, &Task::aborted, [isLegacy]{ + QDir(FS::PathCombine("java",(isLegacy ? "java-legacy" : "java-current"))).removeRecursively(); + }); + + QObject::connect(netJob, &NetJob::finished, [netJob, response, this] { + //delete so that it's not called on a deleted job + QObject::disconnect(this, &Task::aborted, netJob, &NetJob::abort); netJob->deleteLater(); delete response; }); QObject::connect(netJob, &NetJob::progress, this, &JavaDownloader::progress); - QObject::connect(netJob, &NetJob::succeeded, [response, OS, isLegacy, this] { + QObject::connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed); + + QObject::connect(this, &Task::aborted, netJob, &NetJob::abort); + + QObject::connect(netJob, &NetJob::succeeded, [response, OS, isLegacy, this, netJob] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -51,12 +63,16 @@ void JavaDownloader::executeTask() download->addNetAction(Net::Download::makeByteArray(QUrl(url), files)); - QObject::connect(download, &NetJob::finished, [download, files] { + QObject::connect(download, &NetJob::finished, [download, files, this] { + QObject::disconnect(this, &Task::aborted, download, &NetJob::abort); download->deleteLater(); delete files; }); QObject::connect(download, &NetJob::progress, this, &JavaDownloader::progress); - QObject::connect(download, &NetJob::succeeded, [files, isLegacy, this] { + QObject::connect(download, &NetJob::failed, this, &JavaDownloader::emitFailed); + QObject::connect(this, &Task::aborted, download, &NetJob::abort); + + QObject::connect(download, &NetJob::succeeded, [download, files, isLegacy, this] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -99,8 +115,15 @@ void JavaDownloader::executeTask() } elementDownload->addNetAction(dl); } - QObject::connect(elementDownload, &NetJob::finished, [elementDownload] { elementDownload->deleteLater(); }); + QObject::connect(elementDownload, &NetJob::finished, [elementDownload, this] { + QObject::disconnect(this, &Task::aborted, elementDownload, &NetJob::abort); + elementDownload->deleteLater(); + }); QObject::connect(elementDownload, &NetJob::progress, this, &JavaDownloader::progress); + QObject::connect(elementDownload, &NetJob::failed, this, &JavaDownloader::emitFailed); + + + QObject::connect(this, &Task::aborted, elementDownload, &NetJob::abort); QObject::connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); elementDownload->start(); }); @@ -148,12 +171,15 @@ void JavaDownloader::executeTask() ) .arg(javaVersion, azulOS, arch, bitness), metaResponse)); - QObject::connect(downloadJob, &NetJob::finished, [downloadJob, metaResponse] { + QObject::connect(downloadJob, &NetJob::finished, [downloadJob, metaResponse, this] { + QObject::disconnect(this, &Task::aborted, downloadJob, &NetJob::abort); downloadJob->deleteLater(); delete metaResponse; }); + QObject::connect(this, &Task::aborted, downloadJob, &NetJob::abort); + QObject::connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed); QObject::connect(downloadJob, &NetJob::progress, this, &JavaDownloader::progress); - QObject::connect(downloadJob, &NetJob::succeeded, [metaResponse, isLegacy, this] { + QObject::connect(downloadJob, &NetJob::succeeded, [metaResponse, isLegacy, this, downloadJob] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -173,8 +199,13 @@ void JavaDownloader::executeTask() temp->open(); temp->close(); download->addNetAction(Net::Download::makeFile(downloadURL, temp->fileName())); - QObject::connect(download, &NetJob::finished, [download] { download->deleteLater(); }); + QObject::connect(download, &NetJob::finished, [download, this] { + QObject::disconnect(this, &Task::aborted, download, &NetJob::abort); + download->deleteLater(); + }); QObject::connect(download, &NetJob::progress, this, &JavaDownloader::progress); + QObject::connect(download, &NetJob::failed, this, &JavaDownloader::emitFailed); + QObject::connect(this, &Task::aborted, download, &NetJob::abort); QObject::connect(download, &NetJob::succeeded, [isLegacy, file = std::move(temp), downloadURL, this] { setStatus(tr("Extracting java")); auto output = FS::PathCombine(FS::PathCombine(QCoreApplication::applicationDirPath(), "java"), @@ -194,6 +225,14 @@ void JavaDownloader::executeTask() netJob->start(); } +void JavaDownloader::abortNetJob(NetJob* elementDownload) +{ + if(elementDownload->isRunning()){ + elementDownload->abort(); + }else{ + emit elementDownload->aborted(); + } +} void JavaDownloader::showPrompts(QWidget* parent) { QString sys = SysInfo::currentSystem(); @@ -261,10 +300,12 @@ void JavaDownloader::showPrompts(QWidget* parent) auto down = new JavaDownloader(isLegacy, version); ProgressDialog dialog(parent); - dialog.execWithTask(down); - if (box.clickedButton() == both) { + dialog.setSkipButton(true, tr("Abort")); + + if (dialog.execWithTask(down) && box.clickedButton() == both) { auto dwn = new JavaDownloader(false, version); ProgressDialog dg(parent); + dg.setSkipButton(true, tr("Abort")); dg.execWithTask(dwn); } } diff --git a/launcher/JavaDownloader.h b/launcher/JavaDownloader.h index 274a95e49..00ccdf2bc 100644 --- a/launcher/JavaDownloader.h +++ b/launcher/JavaDownloader.h @@ -1,6 +1,7 @@ #pragma once #include +#include "net/NetJob.h" #include "tasks/Task.h" class JavaDownloader : public Task { @@ -10,9 +11,11 @@ class JavaDownloader : public Task { explicit JavaDownloader(bool isLegacy, const QString& OS) : m_isLegacy(isLegacy), m_OS(OS) {} void executeTask() override; + [[nodiscard]] bool canAbort() const override { return true; } static void showPrompts(QWidget* parent = nullptr); private: bool m_isLegacy; const QString& m_OS; + static void abortNetJob(NetJob* elementDownload); }; From 89f1b60538068ac033f7ca1899b4d310eb43f8c2 Mon Sep 17 00:00:00 2001 From: timoreo Date: Mon, 12 Sep 2022 15:00:31 +0200 Subject: [PATCH 014/120] Delete out non-needed functions from SysInfo Delete LaunchContext Signed-off-by: timoreo --- launcher/CMakeLists.txt | 4 +- launcher/SysInfo.cpp | 103 --------------------------- launcher/SysInfo.h | 6 -- launcher/minecraft/LaunchContext.cpp | 39 ---------- launcher/minecraft/LaunchContext.h | 34 --------- 5 files changed, 1 insertion(+), 185 deletions(-) delete mode 100644 launcher/minecraft/LaunchContext.cpp delete mode 100644 launcher/minecraft/LaunchContext.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index c467957a8..4bb686106 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -271,9 +271,7 @@ set(MINECRAFT_SOURCES minecraft/GradleSpecifier.h minecraft/MinecraftInstance.cpp minecraft/MinecraftInstance.h - minecraft/LaunchContext.cpp - minecraft/LaunchContext.h - minecraft/LaunchProfile.cpp + minecraft/LaunchProfile.cpp minecraft/LaunchProfile.h minecraft/Component.cpp minecraft/Component.h diff --git a/launcher/SysInfo.cpp b/launcher/SysInfo.cpp index 010eb84c8..f3ff200fc 100644 --- a/launcher/SysInfo.cpp +++ b/launcher/SysInfo.cpp @@ -1,18 +1,13 @@ #include #include -#include "minecraft/LaunchContext.h" #ifdef Q_OS_MACOS #include #endif -#include #include -#include -#include "MessageLevel.h" #include #include #include #include "java/JavaUtils.h" -#include "FileSystem.h" #include "Commandline.h" #include "Application.h" @@ -67,103 +62,5 @@ QString useQTForArch(){ #endif return qtArch; } - -QString runCheckerForArch(LaunchContext launchContext){ - QString checkerJar = JavaUtils::getJavaCheckPath(); - - if (checkerJar.isEmpty()) - { - qDebug() << "Java checker library could not be found. Please check your installation."; - return useQTForArch(); - } - - QStringList args; - - QProcessPtr process = new QProcess(); - args.append({"-jar", checkerJar}); - process->setArguments(args); - process->setProgram(launchContext.getJavaPath().toString()); - process->setProcessChannelMode(QProcess::SeparateChannels); - process->setProcessEnvironment(CleanEnviroment()); - qDebug() << "Running java checker: " + launchContext.getJavaPath().toString() + args.join(" ");; - - process->start(); - if(!process->waitForFinished(15000)){ - // we've been waiting for 15 seconds! wtf! OR... it already finished. But HOW WOULD THAT HAPPEN? - process->kill(); // die. BUUURNNNN - // fallback to using polymc arch - return useQTForArch(); - } else { - // yay we can use the java arch - QString stdout_javaChecker; - QString stderr_javaChecker; - - // process stdout - QByteArray data = process->readAllStandardOutput(); - QString added = QString::fromLocal8Bit(data); - added.remove('\r'); - stdout_javaChecker += added; - - // process stderr - data = process->readAllStandardError(); - added = QString::fromLocal8Bit(data); - added.remove('\r'); - stderr_javaChecker += added; - - QMap results; -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - QStringList lines = stdout_javaChecker.split("\n", Qt::SkipEmptyParts); -#else - QStringList lines = stdout_javaChecker.split("\n", QString::SkipEmptyParts); -#endif - for(QString line : lines) - { - line = line.trimmed(); - // NOTE: workaround for GH-4125, where garbage is getting printed into stdout on bedrock linux - if (line.contains("/bedrock/strata")) { - continue; - } - -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - auto parts = line.split('=', Qt::SkipEmptyParts); -#else - auto parts = line.split('=', QString::SkipEmptyParts); -#endif - if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty()) - { - continue; - } - else - { - results.insert(parts[0], parts[1]); - } - } - - if(!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor")) - { - // wtf man why - // fallback to using polymc arch - return useQTForArch(); - } - - return results["os.arch"]; - } -} - -QString currentArch(LaunchContext launchContext) { - auto realJavaArchitecture = launchContext.getRealJavaArch().toString(); - if(realJavaArchitecture == ""){ - //BRO WHY NOW I HAVE TO USE A JAVA CHECKER >:( - qDebug() << "SysInfo: BRO I HAVE TO USE A JAVA CHECKER WHY IS JAVA ARCH BORKED"; - launchContext.setRealJavaArch(runCheckerForArch(launchContext)); - realJavaArchitecture = launchContext.getRealJavaArch().toString(); - } - //qDebug() << "SysInfo: realJavaArch = " << realJavaArchitecture; - if(realJavaArchitecture == "aarch64"){ - return "arm64"; - } else { - return realJavaArchitecture; - } -} } diff --git a/launcher/SysInfo.h b/launcher/SysInfo.h index 9107cacb8..3cb1c8de6 100644 --- a/launcher/SysInfo.h +++ b/launcher/SysInfo.h @@ -1,12 +1,6 @@ #include -#include "minecraft/LaunchContext.h" -#ifdef Q_OS_MACOS -#include -#endif namespace SysInfo { QString currentSystem(); -QString currentArch(LaunchContext launchContext); -QString runCheckerForArch(LaunchContext launchContext); QString useQTForArch(); } diff --git a/launcher/minecraft/LaunchContext.cpp b/launcher/minecraft/LaunchContext.cpp deleted file mode 100644 index ea6a549f0..000000000 --- a/launcher/minecraft/LaunchContext.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (C) 2022 Toshit Chawda - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include "LaunchContext.h" - -LaunchContext::LaunchContext(SettingsObjectPtr instanceSettings){ - m_instanceSettings = instanceSettings; -} - -void LaunchContext::setRealJavaArch(QVariant realJavaArch) -{ - m_instanceSettings->set("JavaRealArchitecture", realJavaArch); -} - -QVariant LaunchContext::getRealJavaArch() -{ - return m_instanceSettings->get("JavaRealArchitecture"); -} - -QVariant LaunchContext::getJavaPath() -{ - return m_instanceSettings->get("JavaPath"); -} diff --git a/launcher/minecraft/LaunchContext.h b/launcher/minecraft/LaunchContext.h deleted file mode 100644 index 2c6e1307f..000000000 --- a/launcher/minecraft/LaunchContext.h +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (C) 2022 Toshit Chawda - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include -#include "settings/SettingsObject.h" - -#pragma once - -class LaunchContext -{ - public: - LaunchContext(SettingsObjectPtr instanceSettings); - void setRealJavaArch(QVariant realJavaArch); - QVariant getRealJavaArch(); - QVariant getJavaPath(); - private: - SettingsObjectPtr m_instanceSettings; -}; From 86e3518430917483f35777a25a76159274e72d38 Mon Sep 17 00:00:00 2001 From: timoreo Date: Mon, 12 Sep 2022 16:34:37 +0200 Subject: [PATCH 015/120] Apply most of the suggestions from @flowln Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 366 ++++++++++++++++++------------------ launcher/JavaDownloader.h | 10 +- 2 files changed, 197 insertions(+), 179 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index b0cde7d98..425a7d470 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -9,7 +9,6 @@ #include "SysInfo.h" #include "net/ChecksumValidator.h" #include "net/NetJob.h" -#include "quazip.h" #include "ui/dialogs/ProgressDialog.h" // Quick & dirty struct to store files @@ -25,28 +24,31 @@ void JavaDownloader::executeTask() auto OS = m_OS; auto isLegacy = m_isLegacy; + downloadMojangJavaList(OS, isLegacy); +} +void JavaDownloader::downloadMojangJavaList(const QString& OS, bool isLegacy) +{ auto netJob = new NetJob(QString("JRE::QueryVersions"), APPLICATION->network()); auto response = new QByteArray(); setStatus(tr("Querying mojang meta")); netJob->addNetAction(Net::Download::makeByteArray( QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); - QObject::connect(this, &Task::aborted, [isLegacy]{ - QDir(FS::PathCombine("java",(isLegacy ? "java-legacy" : "java-current"))).removeRecursively(); - }); + connect(this, &Task::aborted, + [isLegacy] { QDir(FS::PathCombine("java", (isLegacy ? "java-legacy" : "java-current"))).removeRecursively(); }); - QObject::connect(netJob, &NetJob::finished, [netJob, response, this] { - //delete so that it's not called on a deleted job - QObject::disconnect(this, &Task::aborted, netJob, &NetJob::abort); + connect(netJob, &NetJob::finished, [netJob, response, this] { + // delete so that it's not called on a deleted job + disconnect(this, &Task::aborted, netJob, &NetJob::abort); netJob->deleteLater(); delete response; }); - QObject::connect(netJob, &NetJob::progress, this, &JavaDownloader::progress); - QObject::connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed); + connect(netJob, &NetJob::progress, this, &JavaDownloader::progress); + connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed); - QObject::connect(this, &Task::aborted, netJob, &NetJob::abort); + connect(this, &Task::aborted, netJob, &NetJob::abort); - QObject::connect(netJob, &NetJob::succeeded, [response, OS, isLegacy, this, netJob] { + connect(netJob, &NetJob::succeeded, [response, OS, isLegacy, this, netJob] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -56,182 +58,190 @@ void JavaDownloader::executeTask() } auto versionArray = Json::ensureArray(Json::ensureObject(doc.object(), OS), isLegacy ? "jre-legacy" : "java-runtime-gamma"); if (!versionArray.empty()) { - setStatus(tr("Downloading java from Mojang")); - auto url = versionArray[0].toObject()["manifest"].toObject()["url"].toString(); - auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); - auto files = new QByteArray(); + parseMojangManifest(isLegacy, versionArray); - download->addNetAction(Net::Download::makeByteArray(QUrl(url), files)); - - QObject::connect(download, &NetJob::finished, [download, files, this] { - QObject::disconnect(this, &Task::aborted, download, &NetJob::abort); - download->deleteLater(); - delete files; - }); - QObject::connect(download, &NetJob::progress, this, &JavaDownloader::progress); - QObject::connect(download, &NetJob::failed, this, &JavaDownloader::emitFailed); - QObject::connect(this, &Task::aborted, download, &NetJob::abort); - - QObject::connect(download, &NetJob::succeeded, [download, files, isLegacy, this] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *files; - return; - } - - // valid json doc, begin making jre spot - auto output = FS::PathCombine(QString("java"), (isLegacy ? "java-legacy" : "java-current")); - FS::ensureFolderPathExists(output); - std::vector toDownload; - auto list = doc.object()["files"].toObject(); - for (const auto& paths : list.keys()) { - auto file = FS::PathCombine(output, paths); - - auto type = list[paths].toObject()["type"].toString(); - if (type == "directory") { - FS::ensureFolderPathExists(file); - } else if (type == "link") { - // this is linux only ! - auto target = FS::PathCombine(file, "../" + list[paths].toObject()["target"].toString()); - QFile(target).link(file); - } else if (type == "file") { - // TODO download compressed version if it exists ? - auto raw = list[paths].toObject()["downloads"].toObject()["raw"].toObject(); - auto isExec = list[paths].toObject()["executable"].toBool(); - auto f = File{ file, raw["url"].toString(), QByteArray::fromHex(raw["sha1"].toString().toLatin1()), isExec }; - toDownload.push_back(f); - } - } - auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network()); - for (const auto& file : toDownload) { - auto dl = Net::Download::makeFile(file.url, file.path); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash)); - if (file.isExec) { - QObject::connect(dl.get(), &Net::Download::succeeded, [file] { - QFile(file.path).setPermissions(QFile(file.path).permissions() | QFileDevice::Permissions(0x1111)); - }); - } - elementDownload->addNetAction(dl); - } - QObject::connect(elementDownload, &NetJob::finished, [elementDownload, this] { - QObject::disconnect(this, &Task::aborted, elementDownload, &NetJob::abort); - elementDownload->deleteLater(); - }); - QObject::connect(elementDownload, &NetJob::progress, this, &JavaDownloader::progress); - QObject::connect(elementDownload, &NetJob::failed, this, &JavaDownloader::emitFailed); - - - QObject::connect(this, &Task::aborted, elementDownload, &NetJob::abort); - QObject::connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); - elementDownload->start(); - }); - download->start(); } else { // mojang does not have a JRE for us, let's get azul zulu - setStatus(tr("Querying Azul meta")); - QString javaVersion = isLegacy ? QString("8.0") : QString("17.0"); - QString azulOS; - QString arch; - QString bitness; - - if (OS == "mac-os-arm64") { - // macos arm64 - azulOS = "macos"; - arch = "arm"; - bitness = "64"; - } else if (OS == "linux-arm64") { - // linux arm64 - azulOS = "linux"; - arch = "arm"; - bitness = "64"; - } else if (OS == "linux-arm") { - // linux arm (32) - azulOS = "linux"; - arch = "arm"; - bitness = "32"; - } else if (OS == "linux"){ - // linux x86 64 (used for debugging, should never reach here) - azulOS = "linux"; - arch = "x86"; - bitness = "64"; - } - auto metaResponse = new QByteArray(); - auto downloadJob = new NetJob(QString("JRE::QueryAzulMeta"), APPLICATION->network()); - downloadJob->addNetAction( - Net::Download::makeByteArray(QString("https://api.azul.com/zulu/download/community/v1.0/bundles/?" - "java_version=%1" - "&os=%2" - "&arch=%3" - "&hw_bitness=%4" - "&ext=zip" // as a zip for all os, even linux NOTE !! Linux ARM is .deb only !! - "&bundle_type=jre" // jre only - "&latest=true" // only get the one latest entry - ) - .arg(javaVersion, azulOS, arch, bitness), - metaResponse)); - QObject::connect(downloadJob, &NetJob::finished, [downloadJob, metaResponse, this] { - QObject::disconnect(this, &Task::aborted, downloadJob, &NetJob::abort); - downloadJob->deleteLater(); - delete metaResponse; - }); - QObject::connect(this, &Task::aborted, downloadJob, &NetJob::abort); - QObject::connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed); - QObject::connect(downloadJob, &NetJob::progress, this, &JavaDownloader::progress); - QObject::connect(downloadJob, &NetJob::succeeded, [metaResponse, isLegacy, this, downloadJob] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *metaResponse; - return; - } - auto array = doc.array(); - if (!array.empty()) { - // JRE found ! download the zip - setStatus(tr("Downloading java from Azul")); - auto downloadURL = QUrl(array[0].toObject()["url"].toString()); - auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); - auto temp = std::make_unique(FS::PathCombine(APPLICATION->root(), "temp", "XXXXXX.zip")); - FS::ensureFolderPathExists(FS::PathCombine(APPLICATION->root(),"temp")); - // Have to open at least once to generate path - temp->open(); - temp->close(); - download->addNetAction(Net::Download::makeFile(downloadURL, temp->fileName())); - QObject::connect(download, &NetJob::finished, [download, this] { - QObject::disconnect(this, &Task::aborted, download, &NetJob::abort); - download->deleteLater(); - }); - QObject::connect(download, &NetJob::progress, this, &JavaDownloader::progress); - QObject::connect(download, &NetJob::failed, this, &JavaDownloader::emitFailed); - QObject::connect(this, &Task::aborted, download, &NetJob::abort); - QObject::connect(download, &NetJob::succeeded, [isLegacy, file = std::move(temp), downloadURL, this] { - setStatus(tr("Extracting java")); - auto output = FS::PathCombine(FS::PathCombine(QCoreApplication::applicationDirPath(), "java"), - isLegacy ? "java-legacy" : "java-current"); - // This should do all of the extracting and creating folders - MMCZip::extractDir(file->fileName(), downloadURL.fileName().chopped(4), output); - emitSucceeded(); - }); - download->start(); - } else { - emitFailed(tr("No suitable JRE found")); - } - }); - downloadJob->start(); + downloadAzulMeta(OS, isLegacy, netJob); } }); netJob->start(); } -void JavaDownloader::abortNetJob(NetJob* elementDownload) +void JavaDownloader::parseMojangManifest(bool isLegacy, const QJsonArray& versionArray) { - if(elementDownload->isRunning()){ - elementDownload->abort(); - }else{ - emit elementDownload->aborted(); + setStatus(tr("Downloading java from Mojang")); + auto url = versionArray[0].toObject()["manifest"].toObject()["url"].toString(); + auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); + auto files = new QByteArray(); + + download->addNetAction(Net::Download::makeByteArray(QUrl(url), files)); + + connect(download, &NetJob::finished, [download, files, this] { + disconnect(this, &Task::aborted, download, &NetJob::abort); + download->deleteLater(); + delete files; + }); + connect(download, &NetJob::progress, this, &JavaDownloader::progress); + connect(download, &NetJob::failed, this, &JavaDownloader::emitFailed); + connect(this, &Task::aborted, download, &NetJob::abort); + + connect(download, &NetJob::succeeded, [files, isLegacy, this] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); + qWarning() << *files; + return; + } + downloadMojangJava(isLegacy, doc); + }); + download->start(); +} +void JavaDownloader::downloadMojangJava(bool isLegacy, const QJsonDocument& doc) +{ // valid json doc, begin making jre spot + auto output = FS::PathCombine(QString("java"), (isLegacy ? "java-legacy" : "java-current")); + FS::ensureFolderPathExists(output); + std::vector toDownload; + auto list = doc.object()["files"].toObject(); + for (const auto& paths : list.keys()) { + auto file = FS::PathCombine(output, paths); + + auto type = list[paths].toObject()["type"].toString(); + if (type == "directory") { + FS::ensureFolderPathExists(file); + } else if (type == "link") { + // this is linux only ! + auto target = FS::PathCombine(file, "../" + list[paths].toObject()["target"].toString()); + QFile(target).link(file); + } else if (type == "file") { + // TODO download compressed version if it exists ? + auto raw = list[paths].toObject()["downloads"].toObject()["raw"].toObject(); + auto isExec = list[paths].toObject()["executable"].toBool(); + auto f = File{ file, raw["url"].toString(), QByteArray::fromHex(raw["sha1"].toString().toLatin1()), isExec }; + toDownload.push_back(f); + } } + auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network()); + for (const auto& file : toDownload) { + auto dl = Net::Download::makeFile(file.url, file.path); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash)); + if (file.isExec) { + connect(dl.get(), &Net::Download::succeeded, + [file] { QFile(file.path).setPermissions(QFile(file.path).permissions() | QFileDevice::Permissions(0x1111)); }); + } + elementDownload->addNetAction(dl); + } + connect(elementDownload, &NetJob::finished, [elementDownload, this] { + disconnect(this, &Task::aborted, elementDownload, &NetJob::abort); + elementDownload->deleteLater(); + }); + connect(elementDownload, &NetJob::progress, this, &JavaDownloader::progress); + connect(elementDownload, &NetJob::failed, this, &JavaDownloader::emitFailed); + + connect(this, &Task::aborted, elementDownload, &NetJob::abort); + connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); + elementDownload->start(); +} +void JavaDownloader::downloadAzulMeta(const QString& OS, bool isLegacy, const NetJob* netJob) +{ + setStatus(tr("Querying Azul meta")); + QString javaVersion = isLegacy ? QString("8.0") : QString("17.0"); + + QString azulOS; + QString arch; + QString bitness; + + mojangOStoAzul(OS, azulOS, arch, bitness); + auto metaResponse = new QByteArray(); + auto downloadJob = new NetJob(QString("JRE::QueryAzulMeta"), APPLICATION->network()); + downloadJob->addNetAction( + Net::Download::makeByteArray(QString("https://api.azul.com/zulu/download/community/v1.0/bundles/?" + "java_version=%1" + "&os=%2" + "&arch=%3" + "&hw_bitness=%4" + "&ext=zip" // as a zip for all os, even linux NOTE !! Linux ARM is .deb only !! + "&bundle_type=jre" // jre only + "&latest=true" // only get the one latest entry + ) + .arg(javaVersion, azulOS, arch, bitness), + metaResponse)); + connect(downloadJob, &NetJob::finished, [downloadJob, metaResponse, this] { + disconnect(this, &Task::aborted, downloadJob, &NetJob::abort); + downloadJob->deleteLater(); + delete metaResponse; + }); + connect(this, &Task::aborted, downloadJob, &NetJob::abort); + connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed); + connect(downloadJob, &NetJob::progress, this, &JavaDownloader::progress); + connect(downloadJob, &NetJob::succeeded, [metaResponse, isLegacy, this] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); + qWarning() << *metaResponse; + return; + } + auto array = doc.array(); + if (!array.empty()) { + downloadAzulJava(isLegacy, array); + } else { + emitFailed(tr("No suitable JRE found")); + } + }); + downloadJob->start(); +} +void JavaDownloader::mojangOStoAzul(const QString& OS, QString& azulOS, QString& arch, QString& bitness) +{ + if (OS == "mac-os-arm64") { + // macos arm64 + azulOS = "macos"; + arch = "arm"; + bitness = "64"; + } else if (OS == "linux-arm64") { + // linux arm64 + azulOS = "linux"; + arch = "arm"; + bitness = "64"; + } else if (OS == "linux-arm") { + // linux arm (32) + azulOS = "linux"; + arch = "arm"; + bitness = "32"; + } else if (OS == "linux") { + // linux x86 64 (used for debugging, should never reach here) + azulOS = "linux"; + arch = "x86"; + bitness = "64"; + } +} +void JavaDownloader::downloadAzulJava(bool isLegacy, const QJsonArray& array) +{ // JRE found ! download the zip + setStatus(tr("Downloading java from Azul")); + auto downloadURL = QUrl(array[0].toObject()["url"].toString()); + auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); + auto temp = std::make_unique(FS::PathCombine(APPLICATION->root(), "temp", "XXXXXX.zip")); + FS::ensureFolderPathExists(FS::PathCombine(APPLICATION->root(), "temp")); + // Have to open at least once to generate path + temp->open(); + temp->close(); + download->addNetAction(Net::Download::makeFile(downloadURL, temp->fileName())); + connect(download, &NetJob::finished, [download, this] { + disconnect(this, &Task::aborted, download, &NetJob::abort); + download->deleteLater(); + }); + connect(download, &NetJob::progress, this, &JavaDownloader::progress); + connect(download, &NetJob::failed, this, &JavaDownloader::emitFailed); + connect(this, &Task::aborted, download, &NetJob::abort); + connect(download, &NetJob::succeeded, [isLegacy, file = std::move(temp), downloadURL, this] { + setStatus(tr("Extracting java")); + auto output = FS::PathCombine(QCoreApplication::applicationDirPath(), "java", isLegacy ? "java-legacy" : "java-current"); + // This should do all of the extracting and creating folders + MMCZip::extractDir(file->fileName(), downloadURL.fileName().chopped(4), output); + emitSucceeded(); + }); + download->start(); } void JavaDownloader::showPrompts(QWidget* parent) { @@ -289,7 +299,7 @@ void JavaDownloader::showPrompts(QWidget* parent) both->setEnabled(false); } if (!yes->isEnabled() && !no->isEnabled()) { - QMessageBox::warning(parent, tr("Already installed !"), tr("Both versions of java are already installed !")); + QMessageBox::warning(parent, tr("Already installed!"), tr("Both versions of java are already installed!")); return; } box.exec(); diff --git a/launcher/JavaDownloader.h b/launcher/JavaDownloader.h index 00ccdf2bc..6ed67263a 100644 --- a/launcher/JavaDownloader.h +++ b/launcher/JavaDownloader.h @@ -17,5 +17,13 @@ class JavaDownloader : public Task { private: bool m_isLegacy; const QString& m_OS; - static void abortNetJob(NetJob* elementDownload); + + void downloadMojangJavaList(const QString& OS, bool isLegacy); + void parseMojangManifest(bool isLegacy, const QJsonArray& versionArray); + void downloadMojangJava(bool isLegacy, const QJsonDocument& doc); + + static void mojangOStoAzul(const QString& OS, QString& azulOS, QString& arch, QString& bitness) ; + void downloadAzulMeta(const QString& OS, bool isLegacy, const NetJob* netJob); + void downloadAzulJava(bool isLegacy, const QJsonArray& array); + }; From a65f20a78920efdb974b78f0c72df95d401ad337 Mon Sep 17 00:00:00 2001 From: timoreo Date: Mon, 12 Sep 2022 17:21:55 +0200 Subject: [PATCH 016/120] Fix a tiny formatting issue Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: timoreo --- launcher/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 4bb686106..c4d9cb74f 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -271,7 +271,7 @@ set(MINECRAFT_SOURCES minecraft/GradleSpecifier.h minecraft/MinecraftInstance.cpp minecraft/MinecraftInstance.h - minecraft/LaunchProfile.cpp + minecraft/LaunchProfile.cpp minecraft/LaunchProfile.h minecraft/Component.cpp minecraft/Component.h From dcbd6cc1afe3495908511fb9179dd27fe8a70c98 Mon Sep 17 00:00:00 2001 From: timoreo Date: Mon, 12 Sep 2022 19:31:07 +0200 Subject: [PATCH 017/120] More Json:: everywhere ! Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index 425a7d470..d0b8c5240 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -71,7 +71,7 @@ void JavaDownloader::downloadMojangJavaList(const QString& OS, bool isLegacy) void JavaDownloader::parseMojangManifest(bool isLegacy, const QJsonArray& versionArray) { setStatus(tr("Downloading java from Mojang")); - auto url = versionArray[0].toObject()["manifest"].toObject()["url"].toString(); + auto url = Json::ensureString(Json::ensureObject(Json::ensureObject(versionArray[0]), "manifest"), "url"); auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); auto files = new QByteArray(); @@ -103,22 +103,22 @@ void JavaDownloader::downloadMojangJava(bool isLegacy, const QJsonDocument& doc) auto output = FS::PathCombine(QString("java"), (isLegacy ? "java-legacy" : "java-current")); FS::ensureFolderPathExists(output); std::vector toDownload; - auto list = doc.object()["files"].toObject(); + auto list = Json::ensureObject(Json::ensureObject(doc.object()), "files"); for (const auto& paths : list.keys()) { auto file = FS::PathCombine(output, paths); - auto type = list[paths].toObject()["type"].toString(); + auto type = Json::requireString(Json::requireObject(list, paths), "type"); if (type == "directory") { FS::ensureFolderPathExists(file); } else if (type == "link") { // this is linux only ! - auto target = FS::PathCombine(file, "../" + list[paths].toObject()["target"].toString()); + auto target = FS::PathCombine(file, "../" + Json::requireString(Json::requireObject(list, paths), "target")); QFile(target).link(file); } else if (type == "file") { // TODO download compressed version if it exists ? - auto raw = list[paths].toObject()["downloads"].toObject()["raw"].toObject(); - auto isExec = list[paths].toObject()["executable"].toBool(); - auto f = File{ file, raw["url"].toString(), QByteArray::fromHex(raw["sha1"].toString().toLatin1()), isExec }; + auto raw = Json::requireObject(Json::requireObject(Json::requireObject(list, paths), "downloads"), "raw"); + auto isExec = Json::ensureBoolean(Json::requireObject(list, paths), "executable", false); + auto f = File{ file, Json::requireString(raw, "url"), QByteArray::fromHex(Json::ensureString(raw, "sha1").toLatin1()), isExec }; toDownload.push_back(f); } } @@ -183,7 +183,7 @@ void JavaDownloader::downloadAzulMeta(const QString& OS, bool isLegacy, const Ne qWarning() << *metaResponse; return; } - auto array = doc.array(); + auto array = Json::ensureArray(doc.array()); if (!array.empty()) { downloadAzulJava(isLegacy, array); } else { From 6a5db12c6a3350b74eb9cd75a526881bc5b68572 Mon Sep 17 00:00:00 2001 From: timoreo Date: Mon, 24 Oct 2022 14:55:51 +0200 Subject: [PATCH 018/120] Apply some more suggestions from @flowln Co-authored-by: flow Signed-off-by: timoreo --- launcher/JavaDownloader.cpp | 82 +++++++++++-------- .../ui/pages/instance/InstanceSettingsPage.ui | 38 ++++----- 2 files changed, 68 insertions(+), 52 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index d0b8c5240..165573599 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -2,8 +2,10 @@ #include #include #include +#include #include "Application.h" #include "FileSystem.h" +#include "InstanceList.h" #include "Json.h" #include "MMCZip.h" #include "SysInfo.h" @@ -34,8 +36,10 @@ void JavaDownloader::downloadMojangJavaList(const QString& OS, bool isLegacy) netJob->addNetAction(Net::Download::makeByteArray( QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); - connect(this, &Task::aborted, - [isLegacy] { QDir(FS::PathCombine("java", (isLegacy ? "java-legacy" : "java-current"))).removeRecursively(); }); + connect(this, &Task::aborted, [isLegacy] { + QDir(FS::PathCombine(QCoreApplication::applicationDirPath(), "java", (isLegacy ? "java-legacy" : "java-current"))) + .removeRecursively(); + }); connect(netJob, &NetJob::finished, [netJob, response, this] { // delete so that it's not called on a deleted job @@ -70,7 +74,7 @@ void JavaDownloader::downloadMojangJavaList(const QString& OS, bool isLegacy) } void JavaDownloader::parseMojangManifest(bool isLegacy, const QJsonArray& versionArray) { - setStatus(tr("Downloading java from Mojang")); + setStatus(tr("Downloading Java from Mojang")); auto url = Json::ensureString(Json::ensureObject(Json::ensureObject(versionArray[0]), "manifest"), "url"); auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); auto files = new QByteArray(); @@ -100,32 +104,41 @@ void JavaDownloader::parseMojangManifest(bool isLegacy, const QJsonArray& versio } void JavaDownloader::downloadMojangJava(bool isLegacy, const QJsonDocument& doc) { // valid json doc, begin making jre spot - auto output = FS::PathCombine(QString("java"), (isLegacy ? "java-legacy" : "java-current")); + auto output = FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java"), (isLegacy ? "java-legacy" : "java-current")); FS::ensureFolderPathExists(output); std::vector toDownload; auto list = Json::ensureObject(Json::ensureObject(doc.object()), "files"); for (const auto& paths : list.keys()) { auto file = FS::PathCombine(output, paths); - auto type = Json::requireString(Json::requireObject(list, paths), "type"); + const QJsonObject& meta = Json::ensureObject(list, paths); + auto type = Json::ensureString(meta, "type"); if (type == "directory") { FS::ensureFolderPathExists(file); } else if (type == "link") { // this is linux only ! - auto target = FS::PathCombine(file, "../" + Json::requireString(Json::requireObject(list, paths), "target")); - QFile(target).link(file); + auto path = Json::ensureString(meta, "target"); + if (!path.isEmpty()) { + auto target = FS::PathCombine(file, "../" + path); + QFile(target).link(file); + } } else if (type == "file") { // TODO download compressed version if it exists ? - auto raw = Json::requireObject(Json::requireObject(Json::requireObject(list, paths), "downloads"), "raw"); - auto isExec = Json::ensureBoolean(Json::requireObject(list, paths), "executable", false); - auto f = File{ file, Json::requireString(raw, "url"), QByteArray::fromHex(Json::ensureString(raw, "sha1").toLatin1()), isExec }; - toDownload.push_back(f); + auto raw = Json::ensureObject(Json::ensureObject(meta, "downloads"), "raw"); + auto isExec = Json::ensureBoolean(meta, "executable", false); + auto url = Json::ensureString(raw, "url"); + if (!url.isEmpty() && QUrl(url).isValid()) { + auto f = File{ file, url, QByteArray::fromHex(Json::ensureString(raw, "sha1").toLatin1()), isExec }; + toDownload.push_back(f); + } } } auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network()); for (const auto& file : toDownload) { auto dl = Net::Download::makeFile(file.url, file.path); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash)); + if (!file.hash.isEmpty()) { + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash)); + } if (file.isExec) { connect(dl.get(), &Net::Download::succeeded, [file] { QFile(file.path).setPermissions(QFile(file.path).permissions() | QFileDevice::Permissions(0x1111)); }); @@ -161,7 +174,7 @@ void JavaDownloader::downloadAzulMeta(const QString& OS, bool isLegacy, const Ne "&os=%2" "&arch=%3" "&hw_bitness=%4" - "&ext=zip" // as a zip for all os, even linux NOTE !! Linux ARM is .deb only !! + "&ext=zip" // as a zip for all os, even linux NOTE !! Linux ARM is .deb or .tar.gz only !! "&bundle_type=jre" // jre only "&latest=true" // only get the one latest entry ) @@ -218,27 +231,30 @@ void JavaDownloader::mojangOStoAzul(const QString& OS, QString& azulOS, QString& } void JavaDownloader::downloadAzulJava(bool isLegacy, const QJsonArray& array) { // JRE found ! download the zip - setStatus(tr("Downloading java from Azul")); + setStatus(tr("Downloading Java from Azul")); auto downloadURL = QUrl(array[0].toObject()["url"].toString()); auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); - auto temp = std::make_unique(FS::PathCombine(APPLICATION->root(), "temp", "XXXXXX.zip")); - FS::ensureFolderPathExists(FS::PathCombine(APPLICATION->root(), "temp")); - // Have to open at least once to generate path - temp->open(); - temp->close(); - download->addNetAction(Net::Download::makeFile(downloadURL, temp->fileName())); + auto path = APPLICATION->instances()->getStagedInstancePath(); + auto temp = FS::PathCombine(path, "azulJRE.zip"); + + download->addNetAction(Net::Download::makeFile(downloadURL, temp)); connect(download, &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download, &NetJob::abort); download->deleteLater(); }); + connect(download, &NetJob::aborted, [path] { APPLICATION->instances()->destroyStagingPath(path); }); connect(download, &NetJob::progress, this, &JavaDownloader::progress); - connect(download, &NetJob::failed, this, &JavaDownloader::emitFailed); + connect(download, &NetJob::failed, this, [this, path](QString reason) { + APPLICATION->instances()->destroyStagingPath(path); + emitFailed(std::move(reason)); + }); connect(this, &Task::aborted, download, &NetJob::abort); - connect(download, &NetJob::succeeded, [isLegacy, file = std::move(temp), downloadURL, this] { + connect(download, &NetJob::succeeded, [isLegacy, temp, downloadURL, path, this] { setStatus(tr("Extracting java")); auto output = FS::PathCombine(QCoreApplication::applicationDirPath(), "java", isLegacy ? "java-legacy" : "java-current"); // This should do all of the extracting and creating folders - MMCZip::extractDir(file->fileName(), downloadURL.fileName().chopped(4), output); + MMCZip::extractDir(temp, downloadURL.fileName().chopped(4), output); + APPLICATION->instances()->destroyStagingPath(path); emitSucceeded(); }); download->start(); @@ -280,26 +296,27 @@ void JavaDownloader::showPrompts(QWidget* parent) return; } // Selection using QMessageBox for java 8 or 17 - QMessageBox box(QMessageBox::Icon::Question, tr("Java version"), - tr("Do you want to download Java version 8 or 17?\n Java 8 is recommended for minecraft versions below 1.17\n Java 17 " - "is recommended for minecraft versions above or equal to 1.17"), - QMessageBox::NoButton, parent); + QMessageBox box( + QMessageBox::Icon::Question, tr("Java version"), + tr("Do you want to download Java version 8 or 17?\n Java 8 is recommended for older Minecraft versions, below 1.17\n Java 17 " + "is recommended for newer Minecraft versions, starting from 1.17"), + QMessageBox::NoButton, parent); auto yes = box.addButton("Java 17", QMessageBox::AcceptRole); auto no = box.addButton("Java 8", QMessageBox::AcceptRole); auto both = box.addButton(tr("Download both"), QMessageBox::AcceptRole); auto cancel = box.addButton(QMessageBox::Cancel); - if (QFileInfo::exists(FS::PathCombine(QString("java"), "java-legacy"))) { + if (QFileInfo::exists(FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java"), "java-legacy"))) { no->setEnabled(false); } - if (QFileInfo::exists(FS::PathCombine(QString("java"), "java-current"))) { + if (QFileInfo::exists(FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java"), "java-current"))) { yes->setEnabled(false); } if (!yes->isEnabled() || !no->isEnabled()) { both->setEnabled(false); } if (!yes->isEnabled() && !no->isEnabled()) { - QMessageBox::warning(parent, tr("Already installed!"), tr("Both versions of java are already installed!")); + QMessageBox::information(parent, tr("Already installed!"), tr("Both versions of Java are already installed!")); return; } box.exec(); @@ -311,8 +328,9 @@ void JavaDownloader::showPrompts(QWidget* parent) auto down = new JavaDownloader(isLegacy, version); ProgressDialog dialog(parent); dialog.setSkipButton(true, tr("Abort")); - - if (dialog.execWithTask(down) && box.clickedButton() == both) { + bool finished_successfully = dialog.execWithTask(down); + // Run another download task for the other option as well! + if (finished_successfully && box.clickedButton() == both) { auto dwn = new JavaDownloader(false, version); ProgressDialog dg(parent); dg.setSkipButton(true, tr("Abort")); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 4ce59a0ae..a28332d5a 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -61,9 +61,6 @@ false - - - @@ -71,20 +68,6 @@ - - - - Browse... - - - - - - - Test - - - @@ -95,7 +78,24 @@ - + + + + + + + Browse... + + + + + + + Test + + + + Download Java... @@ -635,8 +635,6 @@ javaSettingsGroupBox javaPathTextBox javaDetectBtn - javaBrowseBtn - javaTestBtn memoryGroupBox minMemSpinBox maxMemSpinBox From ce6a36c8b57fb9eb0a22c4f70b74e8fa200a88ad Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 28 Jul 2023 14:31:53 +0100 Subject: [PATCH 019/120] Deduplicate fix Signed-off-by: TheKodeToad --- launcher/MMCZip.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 49fd0e707..1a336375b 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -315,11 +315,6 @@ std::optional MMCZip::extractSubDir(QuaZip *zip, const QString & su if (relative_file_name.startsWith('/')) relative_file_name = relative_file_name.mid(1); - // Fix subdirs/files ending with a / getting transformed into absolute paths - if(name.startsWith('/')){ - name = name.mid(1); - } - // Fix weird "folders with a single file get squashed" thing QString sub_path; if (relative_file_name.contains('/') && !relative_file_name.endsWith('/')) { From 5538c1d0afba06d1a639dca45e88b0e94a3742f0 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 28 Jul 2023 15:11:24 +0100 Subject: [PATCH 020/120] Fix compilation (actually this time!), incorporating new changes Signed-off-by: TheKodeToad --- launcher/JavaDownloader.cpp | 55 +++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp index 165573599..f5960bbe9 100644 --- a/launcher/JavaDownloader.cpp +++ b/launcher/JavaDownloader.cpp @@ -30,8 +30,8 @@ void JavaDownloader::executeTask() } void JavaDownloader::downloadMojangJavaList(const QString& OS, bool isLegacy) { - auto netJob = new NetJob(QString("JRE::QueryVersions"), APPLICATION->network()); - auto response = new QByteArray(); + auto netJob = makeShared(QString("JRE::QueryVersions"), APPLICATION->network()); + auto response = std::make_shared(); setStatus(tr("Querying mojang meta")); netJob->addNetAction(Net::Download::makeByteArray( QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); @@ -41,18 +41,17 @@ void JavaDownloader::downloadMojangJavaList(const QString& OS, bool isLegacy) .removeRecursively(); }); - connect(netJob, &NetJob::finished, [netJob, response, this] { + connect(netJob.get(), &NetJob::finished, [netJob, response, this] { // delete so that it's not called on a deleted job - disconnect(this, &Task::aborted, netJob, &NetJob::abort); - netJob->deleteLater(); - delete response; + // FIXME: is this needed? qt should handle this + disconnect(this, &Task::aborted, netJob.get(), &NetJob::abort); }); - connect(netJob, &NetJob::progress, this, &JavaDownloader::progress); - connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed); + connect(netJob.get(), &NetJob::progress, this, &JavaDownloader::progress); + connect(netJob.get(), &NetJob::failed, this, &JavaDownloader::emitFailed); - connect(this, &Task::aborted, netJob, &NetJob::abort); + connect(this, &Task::aborted, netJob.get(), &NetJob::abort); - connect(netJob, &NetJob::succeeded, [response, OS, isLegacy, this, netJob] { + connect(netJob.get(), &NetJob::succeeded, [response, OS, isLegacy, this, netJob] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -66,7 +65,7 @@ void JavaDownloader::downloadMojangJavaList(const QString& OS, bool isLegacy) } else { // mojang does not have a JRE for us, let's get azul zulu - downloadAzulMeta(OS, isLegacy, netJob); + downloadAzulMeta(OS, isLegacy, netJob.get()); } }); @@ -76,21 +75,19 @@ void JavaDownloader::parseMojangManifest(bool isLegacy, const QJsonArray& versio { setStatus(tr("Downloading Java from Mojang")); auto url = Json::ensureString(Json::ensureObject(Json::ensureObject(versionArray[0]), "manifest"), "url"); - auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); - auto files = new QByteArray(); + auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); + auto files = std::make_shared(); download->addNetAction(Net::Download::makeByteArray(QUrl(url), files)); - connect(download, &NetJob::finished, [download, files, this] { - disconnect(this, &Task::aborted, download, &NetJob::abort); - download->deleteLater(); - delete files; + connect(download.get(), &NetJob::finished, [download, files, this] { + disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); - connect(download, &NetJob::progress, this, &JavaDownloader::progress); - connect(download, &NetJob::failed, this, &JavaDownloader::emitFailed); - connect(this, &Task::aborted, download, &NetJob::abort); + connect(download.get(), &NetJob::progress, this, &JavaDownloader::progress); + connect(download.get(), &NetJob::failed, this, &JavaDownloader::emitFailed); + connect(this, &Task::aborted, download.get(), &NetJob::abort); - connect(download, &NetJob::succeeded, [files, isLegacy, this] { + connect(download.get(), &NetJob::succeeded, [files, isLegacy, this] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -166,8 +163,8 @@ void JavaDownloader::downloadAzulMeta(const QString& OS, bool isLegacy, const Ne QString bitness; mojangOStoAzul(OS, azulOS, arch, bitness); - auto metaResponse = new QByteArray(); - auto downloadJob = new NetJob(QString("JRE::QueryAzulMeta"), APPLICATION->network()); + auto metaResponse = std::make_shared(); + auto downloadJob = makeShared(QString("JRE::QueryAzulMeta"), APPLICATION->network()); downloadJob->addNetAction( Net::Download::makeByteArray(QString("https://api.azul.com/zulu/download/community/v1.0/bundles/?" "java_version=%1" @@ -180,15 +177,13 @@ void JavaDownloader::downloadAzulMeta(const QString& OS, bool isLegacy, const Ne ) .arg(javaVersion, azulOS, arch, bitness), metaResponse)); - connect(downloadJob, &NetJob::finished, [downloadJob, metaResponse, this] { - disconnect(this, &Task::aborted, downloadJob, &NetJob::abort); - downloadJob->deleteLater(); - delete metaResponse; + connect(downloadJob.get(), &NetJob::finished, [downloadJob, metaResponse, this] { + disconnect(this, &Task::aborted, downloadJob.get(), &NetJob::abort); }); - connect(this, &Task::aborted, downloadJob, &NetJob::abort); + connect(this, &Task::aborted, downloadJob.get(), &NetJob::abort); connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed); - connect(downloadJob, &NetJob::progress, this, &JavaDownloader::progress); - connect(downloadJob, &NetJob::succeeded, [metaResponse, isLegacy, this] { + connect(downloadJob.get(), &NetJob::progress, this, &JavaDownloader::progress); + connect(downloadJob.get(), &NetJob::succeeded, [metaResponse, isLegacy, this] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); if (parse_error.error != QJsonParseError::NoError) { From f3baa420b2154c37a8f418a090c4392d526482c2 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 16 Aug 2023 13:43:07 +0100 Subject: [PATCH 021/120] Fix broken tab order Signed-off-by: TheKodeToad --- launcher/ui/pages/global/JavaPage.ui | 8 +++++++- launcher/ui/pages/instance/InstanceSettingsPage.ui | 12 ++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index 44289eb86..0bf27fef1 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -320,8 +320,14 @@ minMemSpinBox maxMemSpinBox permGenSpinBox - javaBrowseBtn javaPathTextBox + javaBrowseBtn + javaDownloadBtn + javaDetectBtn + javaTestBtn + skipCompatibilityCheckbox + skipJavaWizardCheckbox + jvmArgsTextBox tabWidget diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index f9e679b2e..08a74671c 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -714,6 +714,12 @@ openGlobalJavaSettingsButton settingsTabs javaSettingsGroupBox + javaPathTextBox + javaBrowseBtn + javaDownloadBtn + javaDetectBtn + javaTestBtn + skipCompatibilityCheckbox memoryGroupBox minMemSpinBox maxMemSpinBox @@ -733,12 +739,6 @@ useNativeOpenALCheck showGameTime recordGameTime - skipCompatibilityCheckbox - javaPathTextBox - javaBrowseBtn - javaDownloadBtn - javaDetectBtn - javaTestBtn miscellaneousSettingsBox closeAfterLaunchCheck quitAfterGameStopCheck From 33cf7066b403e1438fd3c9dd36e33bf5e84c5f29 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 27 Oct 2023 21:51:35 +0300 Subject: [PATCH 022/120] formated the code Signed-off-by: Trial97 --- launcher/ui/widgets/JavaSettingsWidget.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 3c0352b13..63d7aa57c 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -40,7 +40,6 @@ JavaSettingsWidget::JavaSettingsWidget(QWidget* parent) : QWidget(parent) connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaSettingsWidget::javaPathEdited); connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaSettingsWidget::on_javaStatusBtn_clicked); connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaDownloadBtn_clicked); - } void JavaSettingsWidget::setupUi() @@ -274,7 +273,6 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked() void JavaSettingsWidget::on_javaDownloadBtn_clicked() { JavaDownloader::showPrompts(this); - } void JavaSettingsWidget::on_javaStatusBtn_clicked() { From a0e7729aa62a5bb6a83e401dd863e69cbd886edc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 24 Jan 2024 18:26:43 +0200 Subject: [PATCH 023/120] Started workin on stuff Signed-off-by: Trial97 --- launcher/Application.cpp | 18 +- launcher/Application.h | 2 - launcher/CMakeLists.txt | 2 - launcher/JavaCommon.cpp | 30 ++- launcher/JavaCommon.h | 12 +- launcher/MMCZip.cpp | 106 ++++++++++ launcher/MMCZip.h | 28 +++ launcher/SysInfo.cpp | 18 +- launcher/SysInfo.h | 1 + launcher/java/JavaChecker.cpp | 39 ++-- launcher/java/JavaChecker.h | 62 +++--- launcher/java/JavaCheckerJob.cpp | 41 ---- launcher/java/JavaCheckerJob.h | 56 ------ launcher/java/JavaInstallList.cpp | 37 ++-- launcher/java/JavaInstallList.h | 12 +- launcher/java/JavaUtils.h | 5 +- .../java/providers/AdoptiumJavaDownloader.cpp | 119 +++++++++++ .../java/providers/AdoptiumJavaDownloader.h | 36 ++++ .../java/providers/AzulJavaDownloader.cpp | 159 +++++++++++++++ launcher/java/providers/AzulJavaDownloader.h | 37 ++++ .../java/providers/BasicJavaDownloader.cpp | 29 +++ launcher/java/providers/BasicJavaDownloader.h | 41 ++++ .../java/providers/MojangJavaDownloader.cpp | 185 ++++++++++++++++++ .../java/providers/MojanglJavaDownloader.h | 37 ++++ launcher/launch/steps/CheckJava.cpp | 14 +- launcher/launch/steps/CheckJava.h | 4 +- launcher/ui/widgets/JavaSettingsWidget.cpp | 21 +- launcher/ui/widgets/JavaSettingsWidget.h | 4 +- 28 files changed, 908 insertions(+), 247 deletions(-) delete mode 100644 launcher/java/JavaCheckerJob.cpp delete mode 100644 launcher/java/JavaCheckerJob.h create mode 100644 launcher/java/providers/AdoptiumJavaDownloader.cpp create mode 100644 launcher/java/providers/AdoptiumJavaDownloader.h create mode 100644 launcher/java/providers/AzulJavaDownloader.cpp create mode 100644 launcher/java/providers/AzulJavaDownloader.h create mode 100644 launcher/java/providers/BasicJavaDownloader.cpp create mode 100644 launcher/java/providers/BasicJavaDownloader.h create mode 100644 launcher/java/providers/MojangJavaDownloader.cpp create mode 100644 launcher/java/providers/MojanglJavaDownloader.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 661c6c5be..aa702aa7e 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -44,6 +44,7 @@ #include "BuildConfig.h" #include "DataMigrationTask.h" +#include "java/JavaInstallList.h" #include "net/PasteUpload.h" #include "pathmatcher/MultiMatcher.h" #include "pathmatcher/SimplePrefixMatcher.h" @@ -125,6 +126,7 @@ #include #include +#include "SysInfo.h" #ifdef Q_OS_LINUX #include @@ -607,7 +609,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // Memory m_settings->registerSetting({ "MinMemAlloc", "MinMemoryAlloc" }, 512); - m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, suitableMaxMem()); + m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, SysInfo::suitableMaxMem()); m_settings->registerSetting("PermGen", 128); // Java Settings @@ -1667,20 +1669,6 @@ QString Application::getUserAgentUncached() return BuildConfig.USER_AGENT_UNCACHED; } -int Application::suitableMaxMem() -{ - float totalRAM = (float)Sys::getSystemRam() / (float)Sys::mebibyte; - int maxMemoryAlloc; - - // If totalRAM < 6GB, use (totalRAM / 1.5), else 4GB - if (totalRAM < (4096 * 1.5)) - maxMemoryAlloc = (int)(totalRAM / 1.5); - else - maxMemoryAlloc = 4096; - - return maxMemoryAlloc; -} - bool Application::handleDataMigration(const QString& currentData, const QString& oldData, const QString& name, diff --git a/launcher/Application.h b/launcher/Application.h index 7669e08ec..85bf2dff4 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -180,8 +180,6 @@ class Application : public QApplication { void ShowGlobalSettings(class QWidget* parent, QString open_page = QString()); - int suitableMaxMem(); - bool updaterEnabled(); QString updaterBinaryName(); diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 48ca8f085..e735f2081 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -422,8 +422,6 @@ set(SETTINGS_SOURCES set(JAVA_SOURCES java/JavaChecker.h java/JavaChecker.cpp - java/JavaCheckerJob.h - java/JavaCheckerJob.cpp java/JavaInstall.h java/JavaInstall.cpp java/JavaInstallList.h diff --git a/launcher/JavaCommon.cpp b/launcher/JavaCommon.cpp index e16ac9255..cfc3cfe42 100644 --- a/launcher/JavaCommon.cpp +++ b/launcher/JavaCommon.cpp @@ -63,7 +63,7 @@ bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget* parent) return true; } -void JavaCommon::javaWasOk(QWidget* parent, const JavaCheckResult& result) +void JavaCommon::javaWasOk(QWidget* parent, const JavaChecker::Result& result) { QString text; text += QObject::tr( @@ -79,7 +79,7 @@ void JavaCommon::javaWasOk(QWidget* parent, const JavaCheckResult& result) CustomMessageBox::selectable(parent, QObject::tr("Java test success"), text, QMessageBox::Information)->show(); } -void JavaCommon::javaArgsWereBad(QWidget* parent, const JavaCheckResult& result) +void JavaCommon::javaArgsWereBad(QWidget* parent, const JavaChecker::Result& result) { auto htmlError = result.errorLog; QString text; @@ -89,7 +89,7 @@ void JavaCommon::javaArgsWereBad(QWidget* parent, const JavaCheckResult& result) CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show(); } -void JavaCommon::javaBinaryWasBad(QWidget* parent, const JavaCheckResult& result) +void JavaCommon::javaBinaryWasBad(QWidget* parent, const JavaChecker::Result& result) { QString text; text += QObject::tr( @@ -116,34 +116,26 @@ void JavaCommon::TestCheck::run() emit finished(); return; } - checker.reset(new JavaChecker()); + checker.reset(new JavaChecker(m_path, "", 0, 0, 0, 0, this)); connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinished); - checker->m_path = m_path; - checker->performCheck(); + checker->start(); } -void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) +void JavaCommon::TestCheck::checkFinished(JavaChecker::Result result) { - if (result.validity != JavaCheckResult::Validity::Valid) { + if (result.validity != JavaChecker::Result::Validity::Valid) { javaBinaryWasBad(m_parent, result); emit finished(); return; } - checker.reset(new JavaChecker()); + checker.reset(new JavaChecker(m_path, m_args, m_maxMem, m_maxMem, result.javaVersion.requiresPermGen() ? m_permGen : 0, 0, this)); connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinishedWithArgs); - checker->m_path = m_path; - checker->m_args = m_args; - checker->m_minMem = m_minMem; - checker->m_maxMem = m_maxMem; - if (result.javaVersion.requiresPermGen()) { - checker->m_permGen = m_permGen; - } - checker->performCheck(); + checker->start(); } -void JavaCommon::TestCheck::checkFinishedWithArgs(JavaCheckResult result) +void JavaCommon::TestCheck::checkFinishedWithArgs(JavaChecker::Result result) { - if (result.validity == JavaCheckResult::Validity::Valid) { + if (result.validity == JavaChecker::Result::Validity::Valid) { javaWasOk(m_parent, result); emit finished(); return; diff --git a/launcher/JavaCommon.h b/launcher/JavaCommon.h index c96f7a985..7c5510efc 100644 --- a/launcher/JavaCommon.h +++ b/launcher/JavaCommon.h @@ -10,11 +10,11 @@ namespace JavaCommon { bool checkJVMArgs(QString args, QWidget* parent); // Show a dialog saying that the Java binary was usable -void javaWasOk(QWidget* parent, const JavaCheckResult& result); +void javaWasOk(QWidget* parent, const JavaChecker::Result& result); // Show a dialog saying that the Java binary was not usable because of bad options -void javaArgsWereBad(QWidget* parent, const JavaCheckResult& result); +void javaArgsWereBad(QWidget* parent, const JavaChecker::Result& result); // Show a dialog saying that the Java binary was not usable -void javaBinaryWasBad(QWidget* parent, const JavaCheckResult& result); +void javaBinaryWasBad(QWidget* parent, const JavaChecker::Result& result); // Show a dialog if we couldn't find Java Checker void javaCheckNotFound(QWidget* parent); @@ -32,11 +32,11 @@ class TestCheck : public QObject { void finished(); private slots: - void checkFinished(JavaCheckResult result); - void checkFinishedWithArgs(JavaCheckResult result); + void checkFinished(JavaChecker::Result result); + void checkFinishedWithArgs(JavaChecker::Result result); private: - std::shared_ptr checker; + JavaChecker::Ptr checker; QWidget* m_parent = nullptr; QString m_path; QString m_args; diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 3bfe16ab5..78a3b290d 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -507,6 +507,112 @@ bool ExportToZipTask::abort() } return false; } + +void ExtractZipTask::executeTask() +{ + m_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return extractZip(); }); + connect(&m_zip_watcher, &QFutureWatcher::finished, this, &ExtractZipTask::finish); + m_zip_watcher.setFuture(m_zip_future); +} + +auto ExtractZipTask::extractZip() -> ZipResult +{ + auto target = m_output_dir.absolutePath(); + auto target_top_dir = QUrl::fromLocalFile(target); + + QStringList extracted; + + qDebug() << "Extracting subdir" << m_subdirectory << "from" << m_input->getZipName() << "to" << target; + auto numEntries = m_input->getEntriesCount(); + if (numEntries < 0) { + return ZipResult(tr("Failed to enumerate files in archive")); + } + if (numEntries == 0) { + logWarning(tr("Extracting empty archives seems odd...")); + return ZipResult(); + } + if (!m_input->goToFirstFile()) { + return ZipResult(tr("Failed to seek to first file in zip")); + } + + setStatus("Extracting files..."); + setProgress(0, numEntries); + do { + if (m_zip_future.isCanceled()) + return ZipResult(); + setProgress(m_progress + 1, m_progressTotal); + QString file_name = m_input->getCurrentFileName(); + if (!file_name.startsWith(m_subdirectory)) + continue; + + auto relative_file_name = QDir::fromNativeSeparators(file_name.remove(0, m_subdirectory.size())); + auto original_name = relative_file_name; + setStatus("Unziping: " + relative_file_name); + + // Fix subdirs/files ending with a / getting transformed into absolute paths + if (relative_file_name.startsWith('/')) + relative_file_name = relative_file_name.mid(1); + + // Fix weird "folders with a single file get squashed" thing + QString sub_path; + if (relative_file_name.contains('/') && !relative_file_name.endsWith('/')) { + sub_path = relative_file_name.section('/', 0, -2) + '/'; + FS::ensureFolderPathExists(FS::PathCombine(target, sub_path)); + + relative_file_name = relative_file_name.split('/').last(); + } + + QString target_file_path; + if (relative_file_name.isEmpty()) { + target_file_path = target + '/'; + } else { + target_file_path = FS::PathCombine(target_top_dir.toLocalFile(), sub_path, relative_file_name); + if (relative_file_name.endsWith('/') && !target_file_path.endsWith('/')) + target_file_path += '/'; + } + + if (!target_top_dir.isParentOf(QUrl::fromLocalFile(target_file_path))) { + return ZipResult(tr("Extracting %1 was cancelled, because it was effectively outside of the target path %2") + .arg(relative_file_name, target)); + } + + if (!JlCompress::extractFile(m_input.get(), "", target_file_path)) { + JlCompress::removeFile(extracted); + return ZipResult(tr("Failed to extract file %1 to %2").arg(original_name, target_file_path)); + } + + extracted.append(target_file_path); + QFile::setPermissions(target_file_path, + QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser); + + qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path; + } while (m_input->goToNextFile()); + + return ZipResult(); +} + +void ExtractZipTask::finish() +{ + if (m_zip_future.isCanceled()) { + emitAborted(); + } else if (auto result = m_zip_future.result(); result.has_value()) { + emitFailed(result.value()); + } else { + emitSucceeded(); + } +} + +bool ExtractZipTask::abort() +{ + if (m_zip_future.isRunning()) { + m_zip_future.cancel(); + // NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur + // immediately. + return true; + } + return false; +} + #endif } // namespace MMCZip diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index 45b1df0b3..2b396eb9c 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -194,5 +194,33 @@ class ExportToZipTask : public Task { QFuture m_build_zip_future; QFutureWatcher m_build_zip_watcher; }; + +class ExtractZipTask : public Task { + public: + ExtractZipTask(QString input, QDir outputDir, QString subdirectory = "") + : ExtractZipTask(std::make_shared(input), outputDir, subdirectory) + {} + ExtractZipTask(std::shared_ptr input, QDir outputDir, QString subdirectory = "") + : m_input(input), m_output_dir(outputDir), m_subdirectory(subdirectory) + {} + virtual ~ExtractZipTask() = default; + + typedef std::optional ZipResult; + + protected: + virtual void executeTask() override; + bool abort() override; + + ZipResult extractZip(); + void finish(); + + private: + std::shared_ptr m_input; + QDir m_output_dir; + QString m_subdirectory; + + QFuture m_zip_future; + QFutureWatcher m_zip_watcher; +}; #endif } // namespace MMCZip diff --git a/launcher/SysInfo.cpp b/launcher/SysInfo.cpp index ad251e29f..f15dde0e4 100644 --- a/launcher/SysInfo.cpp +++ b/launcher/SysInfo.cpp @@ -1,5 +1,6 @@ #include #include +#include "sys.h" #ifdef Q_OS_MACOS #include #endif @@ -7,9 +8,6 @@ #include #include #include -#include "Application.h" -#include "Commandline.h" -#include "java/JavaUtils.h" #ifdef Q_OS_MACOS bool rosettaDetect() @@ -59,4 +57,18 @@ QString useQTForArch() #endif return qtArch; } + +int suitableMaxMem() +{ + float totalRAM = (float)Sys::getSystemRam() / (float)Sys::mebibyte; + int maxMemoryAlloc; + + // If totalRAM < 6GB, use (totalRAM / 1.5), else 4GB + if (totalRAM < (4096 * 1.5)) + maxMemoryAlloc = (int)(totalRAM / 1.5); + else + maxMemoryAlloc = 4096; + + return maxMemoryAlloc; +} } // namespace SysInfo diff --git a/launcher/SysInfo.h b/launcher/SysInfo.h index 3650bf008..499c3b1dd 100644 --- a/launcher/SysInfo.h +++ b/launcher/SysInfo.h @@ -3,4 +3,5 @@ namespace SysInfo { QString currentSystem(); QString useQTForArch(); +int suitableMaxMem(); } // namespace SysInfo diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index 20caba189..7271c0d09 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -40,14 +40,13 @@ #include #include -#include "Application.h" #include "Commandline.h" -#include "FileSystem.h" -#include "JavaUtils.h" +#include "java/JavaUtils.h" -JavaChecker::JavaChecker(QObject* parent) : QObject(parent) {} +JavaChecker::JavaChecker(QString path, QString args, int minMem, int maxMem, int permGen, int id, QObject* parent) + : Task(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen), m_id(id){}; -void JavaChecker::performCheck() +void JavaChecker::executeTask() { QString checkerJar = JavaUtils::getJavaCheckPath(); @@ -69,7 +68,7 @@ void JavaChecker::performCheck() if (m_maxMem != 0) { args << QString("-Xmx%1m").arg(m_maxMem); } - if (m_permGen != 64) { + if (m_permGen != 64 && m_permGen != 0) { args << QString("-XX:PermSize=%1m").arg(m_permGen); } @@ -112,11 +111,10 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) QProcessPtr _process = process; process.reset(); - JavaCheckResult result; - { - result.path = m_path; - result.id = m_id; - } + Result result = { + m_path, + m_id, + }; result.errorLog = m_stderr; result.outLog = m_stdout; qDebug() << "STDOUT" << m_stdout; @@ -124,8 +122,9 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) qDebug() << "Java checker finished with status" << status << "exit code" << exitcode; if (status == QProcess::CrashExit || exitcode == 1) { - result.validity = JavaCheckResult::Validity::Errored; + result.validity = Result::Validity::Errored; emit checkFinished(result); + emitSucceeded(); return; } @@ -158,8 +157,9 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) } if (!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor") || !success) { - result.validity = JavaCheckResult::Validity::ReturnedInvalidData; + result.validity = Result::Validity::ReturnedInvalidData; emit checkFinished(result); + emitSucceeded(); return; } @@ -168,7 +168,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) auto java_vendor = results["java.vendor"]; bool is_64 = os_arch == "x86_64" || os_arch == "amd64" || os_arch == "aarch64" || os_arch == "arm64"; - result.validity = JavaCheckResult::Validity::Valid; + result.validity = Result::Validity::Valid; result.is_64bit = is_64; result.mojangPlatform = is_64 ? "64" : "32"; result.realPlatform = os_arch; @@ -176,6 +176,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) result.javaVendor = java_vendor; qDebug() << "Java checker succeeded."; emit checkFinished(result); + emitSucceeded(); } void JavaChecker::error(QProcess::ProcessError err) @@ -187,15 +188,9 @@ void JavaChecker::error(QProcess::ProcessError err) qDebug() << "Native environment:"; qDebug() << QProcessEnvironment::systemEnvironment().toStringList(); killTimer.stop(); - JavaCheckResult result; - { - result.path = m_path; - result.id = m_id; - } - - emit checkFinished(result); - return; + emit checkFinished({ m_path, m_id }); } + emitSucceeded(); } void JavaChecker::timeout() diff --git a/launcher/java/JavaChecker.h b/launcher/java/JavaChecker.h index 7111f8522..0c6191c21 100644 --- a/launcher/java/JavaChecker.h +++ b/launcher/java/JavaChecker.h @@ -3,49 +3,51 @@ #include #include -#include "QObjectPtr.h" - #include "JavaVersion.h" +#include "QObjectPtr.h" +#include "tasks/Task.h" -class JavaChecker; - -struct JavaCheckResult { - QString path; - QString mojangPlatform; - QString realPlatform; - JavaVersion javaVersion; - QString javaVendor; - QString outLog; - QString errorLog; - bool is_64bit = false; - int id; - enum class Validity { Errored, ReturnedInvalidData, Valid } validity = Validity::Errored; -}; - -using QProcessPtr = shared_qobject_ptr; -using JavaCheckerPtr = shared_qobject_ptr; -class JavaChecker : public QObject { +class JavaChecker : public Task { Q_OBJECT public: - explicit JavaChecker(QObject* parent = 0); - void performCheck(); + using QProcessPtr = shared_qobject_ptr; + using Ptr = shared_qobject_ptr; - QString m_path; - QString m_args; - int m_id = 0; - int m_minMem = 0; - int m_maxMem = 0; - int m_permGen = 64; + struct Result { + QString path; + int id; + QString mojangPlatform; + QString realPlatform; + JavaVersion javaVersion; + QString javaVendor; + QString outLog; + QString errorLog; + bool is_64bit = false; + enum class Validity { Errored, ReturnedInvalidData, Valid } validity = Validity::Errored; + }; + + explicit JavaChecker(QString path, QString args, int minMem = 0, int maxMem = 0, int permGen = 0, int id = 0, QObject* parent = 0); signals: - void checkFinished(JavaCheckResult result); + void checkFinished(Result result); + + protected: + virtual void executeTask() override; private: QProcessPtr process; QTimer killTimer; QString m_stdout; QString m_stderr; - public slots: + + QString m_path; + QString m_args; + int m_minMem = 0; + int m_maxMem = 0; + int m_permGen = 64; + int m_id = 0; + + private slots: void timeout(); void finished(int exitcode, QProcess::ExitStatus); void error(QProcess::ProcessError); diff --git a/launcher/java/JavaCheckerJob.cpp b/launcher/java/JavaCheckerJob.cpp deleted file mode 100644 index 870e2a09a..000000000 --- a/launcher/java/JavaCheckerJob.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* 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 "JavaCheckerJob.h" - -#include - -void JavaCheckerJob::partFinished(JavaCheckResult result) -{ - num_finished++; - qDebug() << m_job_name.toLocal8Bit() << "progress:" << num_finished << "/" << javacheckers.size(); - setProgress(num_finished, javacheckers.size()); - - javaresults.replace(result.id, result); - - if (num_finished == javacheckers.size()) { - emitSucceeded(); - } -} - -void JavaCheckerJob::executeTask() -{ - qDebug() << m_job_name.toLocal8Bit() << " started."; - for (auto iter : javacheckers) { - javaresults.append(JavaCheckResult()); - connect(iter.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished); - iter->performCheck(); - } -} diff --git a/launcher/java/JavaCheckerJob.h b/launcher/java/JavaCheckerJob.h deleted file mode 100644 index ddf827968..000000000 --- a/launcher/java/JavaCheckerJob.h +++ /dev/null @@ -1,56 +0,0 @@ -/* 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 -#include "JavaChecker.h" -#include "tasks/Task.h" - -class JavaCheckerJob; -using JavaCheckerJobPtr = shared_qobject_ptr; - -// FIXME: this just seems horribly redundant -class JavaCheckerJob : public Task { - Q_OBJECT - public: - explicit JavaCheckerJob(QString job_name) : Task(), m_job_name(job_name){}; - virtual ~JavaCheckerJob(){}; - - bool addJavaCheckerAction(JavaCheckerPtr base) - { - javacheckers.append(base); - // if this is already running, the action needs to be started right away! - if (isRunning()) { - setProgress(num_finished, javacheckers.size()); - connect(base.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished); - base->performCheck(); - } - return true; - } - QList getResults() { return javaresults; } - - private slots: - void partFinished(JavaCheckResult result); - - protected: - virtual void executeTask() override; - - private: - QString m_job_name; - QList javacheckers; - QList javaresults; - int num_finished = 0; -}; diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index d8be4963f..ef99d6853 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -38,11 +38,13 @@ #include #include +#include -#include "java/JavaCheckerJob.h" +#include "Application.h" +#include "java/JavaChecker.h" #include "java/JavaInstallList.h" #include "java/JavaUtils.h" -#include "minecraft/VersionFilterData.h" +#include "tasks/ConcurrentTask.h" JavaInstallList::JavaInstallList(QObject* parent) : BaseVersionList(parent) {} @@ -55,7 +57,7 @@ Task::Ptr JavaInstallList::getLoadTask() Task::Ptr JavaInstallList::getCurrentTask() { if (m_status == Status::InProgress) { - return m_loadTask; + return m_load_task; } return nullptr; } @@ -64,8 +66,8 @@ void JavaInstallList::load() { if (m_status != Status::InProgress) { m_status = Status::InProgress; - m_loadTask.reset(new JavaListLoadTask(this)); - m_loadTask->start(); + m_load_task.reset(new JavaListLoadTask(this)); + m_load_task->start(); } } @@ -129,7 +131,7 @@ void JavaInstallList::updateListData(QList versions) } endResetModel(); m_status = Status::Done; - m_loadTask.reset(); + m_load_task.reset(); } bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right) @@ -149,11 +151,9 @@ void JavaInstallList::sortVersions() JavaListLoadTask::JavaListLoadTask(JavaInstallList* vlist) : Task() { m_list = vlist; - m_currentRecommended = NULL; + m_current_recommended = NULL; } -JavaListLoadTask::~JavaListLoadTask() {} - void JavaListLoadTask::executeTask() { setStatus(tr("Detecting Java installations...")); @@ -161,20 +161,17 @@ void JavaListLoadTask::executeTask() JavaUtils ju; QList candidate_paths = ju.FindJavaPaths(); - m_job.reset(new JavaCheckerJob("Java detection")); + ConcurrentTask::Ptr job(new ConcurrentTask(this, "Java detection", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())); + m_job.reset(job); connect(m_job.get(), &Task::finished, this, &JavaListLoadTask::javaCheckerFinished); connect(m_job.get(), &Task::progress, this, &Task::setProgress); qDebug() << "Probing the following Java paths: "; int id = 0; for (QString candidate : candidate_paths) { - qDebug() << " " << candidate; - - auto candidate_checker = new JavaChecker(); - candidate_checker->m_path = candidate; - candidate_checker->m_id = id; - m_job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker)); - + auto checker = new JavaChecker(candidate, "", 0, 0, 0, id, this); + connect(checker, &JavaChecker::checkFinished, [this](JavaChecker::Result result) { m_results << result; }); + job->addTask(Task::Ptr(checker)); id++; } @@ -184,11 +181,11 @@ void JavaListLoadTask::executeTask() void JavaListLoadTask::javaCheckerFinished() { QList candidates; - auto results = m_job->getResults(); + std::sort(m_results.begin(), m_results.end(), [](JavaChecker::Result a, JavaChecker::Result b) { return a.id < b.id; }); qDebug() << "Found the following valid Java installations:"; - for (JavaCheckResult result : results) { - if (result.validity == JavaCheckResult::Validity::Valid) { + for (auto result : m_results) { + if (result.validity == JavaChecker::Result::Validity::Valid) { JavaInstallPtr javaVersion(new JavaInstall()); javaVersion->id = result.javaVersion; diff --git a/launcher/java/JavaInstallList.h b/launcher/java/JavaInstallList.h index 1eebadf23..08f0b310d 100644 --- a/launcher/java/JavaInstallList.h +++ b/launcher/java/JavaInstallList.h @@ -19,9 +19,9 @@ #include #include "BaseVersionList.h" +#include "java/JavaChecker.h" #include "tasks/Task.h" -#include "JavaCheckerJob.h" #include "JavaInstall.h" #include "QObjectPtr.h" @@ -53,7 +53,7 @@ class JavaInstallList : public BaseVersionList { protected: Status m_status = Status::NotDone; - shared_qobject_ptr m_loadTask; + shared_qobject_ptr m_load_task; QList m_vlist; }; @@ -62,14 +62,16 @@ class JavaListLoadTask : public Task { public: explicit JavaListLoadTask(JavaInstallList* vlist); - virtual ~JavaListLoadTask(); + virtual ~JavaListLoadTask() = default; + protected: void executeTask() override; public slots: void javaCheckerFinished(); protected: - shared_qobject_ptr m_job; + Task::Ptr m_job; JavaInstallList* m_list; - JavaInstall* m_currentRecommended; + JavaInstall* m_current_recommended; + QList m_results; }; diff --git a/launcher/java/JavaUtils.h b/launcher/java/JavaUtils.h index 616179706..c052ca325 100644 --- a/launcher/java/JavaUtils.h +++ b/launcher/java/JavaUtils.h @@ -15,10 +15,9 @@ #pragma once +#include #include - -#include "JavaChecker.h" -#include "JavaInstallList.h" +#include "java/JavaInstall.h" #ifdef Q_OS_WIN #include diff --git a/launcher/java/providers/AdoptiumJavaDownloader.cpp b/launcher/java/providers/AdoptiumJavaDownloader.cpp new file mode 100644 index 000000000..4f8499d4a --- /dev/null +++ b/launcher/java/providers/AdoptiumJavaDownloader.cpp @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "java/providers/AdoptiumJavaDownloader.h" +#include +#include +#include "MMCZip.h" + +#include "Application.h" +#include "net/NetJob.h" +#include "tasks/Task.h" + +void AdoptiumJavaDownloader::executeTask() +{ + downloadJava(); +}; + +QString AdoptiumJavaDownloader::getArch() const +{ + if (m_os_arch == "arm64") + return "aarch64"; + if (m_os_arch.isEmpty()) + return "x86"; + return m_os_arch; +} + +void AdoptiumJavaDownloader::downloadJava() +{ + // JRE found ! download the zip + setStatus(tr("Downloading Java from Adoptium")); + + auto javaVersion = m_is_legacy ? QString("8") : QString("17"); + auto azulOS = m_os_name == "osx" ? "mac" : m_os_name; + auto arch = getArch(); + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("java", "adoptiumJRE.zip"); + + auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); + download->addNetAction(Net::Download::makeCached( + QString("https://api.adoptium.net/v3/binary/latest/%1/ga/%2/%3/jre/hotspot/normal/eclipse").arg(javaVersion, azulOS, arch), entry)); + auto fullPath = entry->getFullPath(); + + connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); + // connect(download.get(), &NetJob::aborted, [path] { APPLICATION->instances()->destroyStagingPath(path); }); + connect(download.get(), &NetJob::progress, this, &AdoptiumJavaDownloader::progress); + connect(download.get(), &NetJob::failed, this, &AdoptiumJavaDownloader::emitFailed); + connect(this, &Task::aborted, download.get(), &NetJob::abort); + connect(download.get(), &NetJob::succeeded, [this, fullPath] { + // This should do all of the extracting and creating folders + extractJava(fullPath); + }); + download->start(); +}; + +void AdoptiumJavaDownloader::extractJava(QString input) +{ + setStatus(tr("Extracting java")); + auto zip = std::make_shared(input); + auto files = zip->getFileNameList(); + if (files.isEmpty()) { + emitFailed("Empty archive"); + return; + } + auto zipTask = makeShared(input, m_final_path, files[0]); + + auto progressStep = std::make_shared(); + connect(zipTask.get(), &Task::finished, this, [this, progressStep] { + progressStep->state = TaskStepState::Succeeded; + stepProgress(*progressStep); + }); + + connect(this, &Task::aborted, zipTask.get(), &Task::abort); + connect(zipTask.get(), &Task::finished, [zipTask, this] { disconnect(this, &Task::aborted, zipTask.get(), &Task::abort); }); + + connect(zipTask.get(), &Task::succeeded, this, &AdoptiumJavaDownloader::emitSucceeded); + connect(zipTask.get(), &Task::aborted, this, &AdoptiumJavaDownloader::emitAborted); + connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) { + progressStep->state = TaskStepState::Failed; + stepProgress(*progressStep); + emitFailed(reason); + }); + connect(zipTask.get(), &Task::stepProgress, this, &AdoptiumJavaDownloader::propagateStepProgress); + + connect(zipTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { + progressStep->update(current, total); + stepProgress(*progressStep); + }); + connect(zipTask.get(), &Task::status, this, [this, progressStep](QString status) { + progressStep->status = status; + stepProgress(*progressStep); + }); + zipTask->start(); +}; + +static const QStringList supportedOs = { + "linux", "windows", "mac", "solaris", "aix", "alpine-linux", +}; + +static const QStringList supportedArch = { + "x64", "x86", "x32", "ppc64", "ppc64le", "s390x", "aarch64", "arm", "sparcv9", "riscv64", +}; + +bool AdoptiumJavaDownloader::isSupported() const +{ + return supportedOs.contains(m_os_name == "osx" ? "mac" : m_os_name) && supportedArch.contains(getArch()); +}; \ No newline at end of file diff --git a/launcher/java/providers/AdoptiumJavaDownloader.h b/launcher/java/providers/AdoptiumJavaDownloader.h new file mode 100644 index 000000000..f0ae6239b --- /dev/null +++ b/launcher/java/providers/AdoptiumJavaDownloader.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "java/providers/BasicJavaDownloader.h" + +class AdoptiumJavaDownloader : public BasicJavaDownloader { + Q_OBJECT + public: + void executeTask() override; + + virtual QString name() const override { return "Adoptium"; }; + virtual bool isSupported() const override; + private slots: + void downloadJava(); + void extractJava(QString input); + + private: + QString getArch() const; +}; \ No newline at end of file diff --git a/launcher/java/providers/AzulJavaDownloader.cpp b/launcher/java/providers/AzulJavaDownloader.cpp new file mode 100644 index 000000000..674da592e --- /dev/null +++ b/launcher/java/providers/AzulJavaDownloader.cpp @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "java/providers/AzulJavaDownloader.h" +#include +#include "MMCZip.h" + +#include "Application.h" +#include "Json.h" +#include "net/NetJob.h" +#include "tasks/Task.h" + +void AzulJavaDownloader::executeTask() +{ + downloadJavaList(); +}; + +void AzulJavaDownloader::downloadJavaList() +{ + setStatus(tr("Querying Azul meta")); + + auto javaVersion = m_is_legacy ? QString("8.0") : QString("17.0"); + auto azulOS = m_os_name == "osx" ? "macos" : m_os_name; + auto arch = getArch(); + auto metaResponse = std::make_shared(); + auto downloadJob = makeShared(QString("JRE::QueryAzulMeta"), APPLICATION->network()); + downloadJob->addNetAction(Net::Download::makeByteArray(QString("https://api.azul.com/metadata/v1/zulu/packages/?" + "java_version=%1" + "&os=%2" + "&arch=%3" + "&archive_type=zip" + "&java_package_type=jre" + "&support_term=lts" + "&latest=true" + "status=ga" + "&availability_types=CA" + "&page=1" + "&page_size=1") + .arg(javaVersion, azulOS, arch), + metaResponse)); + connect(downloadJob.get(), &NetJob::finished, + [downloadJob, metaResponse, this] { disconnect(this, &Task::aborted, downloadJob.get(), &NetJob::abort); }); + connect(this, &Task::aborted, downloadJob.get(), &NetJob::abort); + connect(downloadJob.get(), &NetJob::failed, this, &AzulJavaDownloader::emitFailed); + connect(downloadJob.get(), &NetJob::progress, this, &AzulJavaDownloader::progress); + connect(downloadJob.get(), &NetJob::succeeded, [metaResponse, this] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); + qWarning() << *metaResponse; + return; + } + auto array = Json::ensureArray(doc.array()); + if (!array.empty()) { + downloadJava(array); + } else { + emitFailed(tr("No suitable JRE found")); + } + }); + downloadJob->start(); +}; + +QString AzulJavaDownloader::getArch() const +{ + if (m_os_arch == "arm64") + return "aarch64"; + if (m_os_arch == "arm") + return "aarch32"; + if (m_os_arch.isEmpty()) + return "x86"; + return m_os_arch; +} + +void AzulJavaDownloader::downloadJava(const QJsonArray& array) +{ + // JRE found ! download the zip + setStatus(tr("Downloading Java from Azul")); + + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("java", "azulJRE.zip"); + + auto downloadURL = QUrl(array[0].toObject()["url"].toString()); + auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); + download->addNetAction(Net::Download::makeCached(downloadURL, entry)); + auto fullPath = entry->getFullPath(); + + connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); + // connect(download.get(), &NetJob::aborted, [path] { APPLICATION->instances()->destroyStagingPath(path); }); + connect(download.get(), &NetJob::progress, this, &AzulJavaDownloader::progress); + connect(download.get(), &NetJob::failed, this, &AzulJavaDownloader::emitFailed); + connect(this, &Task::aborted, download.get(), &NetJob::abort); + connect(download.get(), &NetJob::succeeded, [downloadURL, this, fullPath] { + // This should do all of the extracting and creating folders + extractJava(fullPath, downloadURL.fileName().chopped(4)); + }); + download->start(); +}; + +void AzulJavaDownloader::extractJava(QString input, QString subdirectory) +{ + setStatus(tr("Extracting java")); + auto zipTask = makeShared(input, m_final_path, subdirectory); + + auto progressStep = std::make_shared(); + connect(zipTask.get(), &Task::finished, this, [this, progressStep] { + progressStep->state = TaskStepState::Succeeded; + stepProgress(*progressStep); + }); + + connect(this, &Task::aborted, zipTask.get(), &Task::abort); + connect(zipTask.get(), &Task::finished, [zipTask, this] { disconnect(this, &Task::aborted, zipTask.get(), &Task::abort); }); + + connect(zipTask.get(), &Task::succeeded, this, &AzulJavaDownloader::emitSucceeded); + connect(zipTask.get(), &Task::aborted, this, &AzulJavaDownloader::emitAborted); + connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) { + progressStep->state = TaskStepState::Failed; + stepProgress(*progressStep); + emitFailed(reason); + }); + connect(zipTask.get(), &Task::stepProgress, this, &AzulJavaDownloader::propagateStepProgress); + + connect(zipTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { + progressStep->update(current, total); + stepProgress(*progressStep); + }); + connect(zipTask.get(), &Task::status, this, [this, progressStep](QString status) { + progressStep->status = status; + stepProgress(*progressStep); + }); + zipTask->start(); +}; + +static const QStringList supportedOs = { + "macos", "linux", "windows", "linux-musl", "linux-glibc", "qnx", "solaris", "aix", +}; + +static const QStringList supportedArch = { + "x86", "x64", "amd64", "i686", "arm", "aarch64", "aarch32", "aarch32sf", "aarch32hf", "ppc", + "ppc64", "ppc32", "ppc32hf", "ppc32spe", "sparc", "sparc64", "sparc32", "sparcv9", "sparcv9-64", "sparcv9-32", +}; + +bool AzulJavaDownloader::isSupported() const +{ + return supportedOs.contains(m_os_name == "osx" ? "macos" : m_os_name) && supportedArch.contains(getArch()); +}; \ No newline at end of file diff --git a/launcher/java/providers/AzulJavaDownloader.h b/launcher/java/providers/AzulJavaDownloader.h new file mode 100644 index 000000000..c4bc8c761 --- /dev/null +++ b/launcher/java/providers/AzulJavaDownloader.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "java/providers/BasicJavaDownloader.h" + +class AzulJavaDownloader : public BasicJavaDownloader { + Q_OBJECT + public: + void executeTask() override; + + virtual QString name() const override { return "Azul"; }; + virtual bool isSupported() const override; + private slots: + void downloadJavaList(); + void downloadJava(const QJsonArray& doc); + void extractJava(QString input, QString subdirectory); + + private: + QString getArch() const; +}; \ No newline at end of file diff --git a/launcher/java/providers/BasicJavaDownloader.cpp b/launcher/java/providers/BasicJavaDownloader.cpp new file mode 100644 index 000000000..9f353d9c1 --- /dev/null +++ b/launcher/java/providers/BasicJavaDownloader.cpp @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "java/providers/BasicJavaDownloader.h" + +#include "SysInfo.h" +#include "tasks/Task.h" + +BasicJavaDownloader::BasicJavaDownloader(QString final_path, bool m_is_legacy, QObject* parent) + : Task(parent) + , m_os_name(SysInfo::currentSystem()) + , m_os_arch(SysInfo::useQTForArch()) + , m_final_path(final_path) + , m_is_legacy(m_is_legacy) +{} diff --git a/launcher/java/providers/BasicJavaDownloader.h b/launcher/java/providers/BasicJavaDownloader.h new file mode 100644 index 000000000..34c944ec8 --- /dev/null +++ b/launcher/java/providers/BasicJavaDownloader.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "tasks/Task.h" + +class BasicJavaDownloader : public Task { + Q_OBJECT + public: + BasicJavaDownloader(QString final_path, bool m_is_legacy = false, QObject* parent = nullptr); + virtual ~BasicJavaDownloader() = default; + + [[nodiscard]] bool canAbort() const override { return true; } + + virtual QString name() const = 0; + virtual bool isSupported() const = 0; + + protected: + QString m_os_name; + QString m_os_arch; + QString m_final_path; + bool m_is_legacy; + + Task::Ptr m_current_task; +}; \ No newline at end of file diff --git a/launcher/java/providers/MojangJavaDownloader.cpp b/launcher/java/providers/MojangJavaDownloader.cpp new file mode 100644 index 000000000..fc2a17e94 --- /dev/null +++ b/launcher/java/providers/MojangJavaDownloader.cpp @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "java/providers/MojanglJavaDownloader.h" + +#include "Application.h" +#include "FileSystem.h" +#include "Json.h" +#include "net/ChecksumValidator.h" +#include "net/NetJob.h" + +struct File { + QString path; + QString url; + QByteArray hash; + bool isExec; +}; + +void MojangJavaDownloader::executeTask() +{ + downloadJavaList(); +}; + +void MojangJavaDownloader::downloadJavaList() +{ + auto netJob = makeShared(QString("JRE::QueryVersions"), APPLICATION->network()); + auto response = std::make_shared(); + setStatus(tr("Querying mojang meta")); + netJob->addNetAction(Net::Download::makeByteArray( + QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); + + connect(netJob.get(), &NetJob::finished, [netJob, this] { + // delete so that it's not called on a deleted job + // FIXME: is this needed? qt should handle this + disconnect(this, &Task::aborted, netJob.get(), &NetJob::abort); + }); + connect(this, &Task::aborted, netJob.get(), &NetJob::abort); + + connect(netJob.get(), &NetJob::progress, this, &MojangJavaDownloader::progress); + connect(netJob.get(), &NetJob::failed, this, &MojangJavaDownloader::emitFailed); + connect(netJob.get(), &NetJob::succeeded, [response, this, netJob] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); + qWarning() << *response; + emitFailed(parse_error.errorString()); + return; + } + auto versionArray = Json::ensureArray(Json::ensureObject(doc.object(), getOS()), m_is_legacy ? "jre-legacy" : "java-runtime-gamma"); + if (!versionArray.empty()) { + parseManifest(versionArray); + + } else { + // mojang does not have a JRE for us, so fail + emitFailed("No suitable JRE found"); + } + }); + + netJob->start(); +}; + +QString MojangJavaDownloader::getOS() const +{ + if (m_os_name == "windows") { + if (m_os_arch == "x86_64") { + return "windows-x64"; + } + if (m_os_arch == "i386") { + return "windows-x86"; + } + // Unknown, maybe arm, appending arch for downloader + return "windows-" + m_os_arch; + } + if (m_os_name == "osx") { + if (m_os_arch == "arm64") { + return "mac-os-arm64"; + } + return "mac-os"; + } + if (m_os_name == "linux") { + if (m_os_arch == "x86_64") { + return "linux"; + } + // will work for i386, and arm(64) + return "linux-" + m_os_arch; + } + return {}; +} +void MojangJavaDownloader::parseManifest(const QJsonArray& versionArray) +{ + setStatus(tr("Downloading Java from Mojang")); + auto url = Json::ensureString(Json::ensureObject(Json::ensureObject(versionArray[0]), "manifest"), "url"); + auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); + auto files = std::make_shared(); + + download->addNetAction(Net::Download::makeByteArray(QUrl(url), files)); + + connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); + connect(download.get(), &NetJob::progress, this, &MojangJavaDownloader::progress); + connect(download.get(), &NetJob::failed, this, &MojangJavaDownloader::emitFailed); + connect(this, &Task::aborted, download.get(), &NetJob::abort); + + connect(download.get(), &NetJob::succeeded, [files, this] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); + qWarning() << *files; + emitFailed(parse_error.errorString()); + return; + } + downloadJava(doc); + }); + download->start(); +}; + +void MojangJavaDownloader::downloadJava(const QJsonDocument& doc) +{ + // valid json doc, begin making jre spot + FS::ensureFolderPathExists(m_final_path); + std::vector toDownload; + auto list = Json::ensureObject(Json::ensureObject(doc.object()), "files"); + for (const auto& paths : list.keys()) { + auto file = FS::PathCombine(m_final_path, paths); + + const QJsonObject& meta = Json::ensureObject(list, paths); + auto type = Json::ensureString(meta, "type"); + if (type == "directory") { + FS::ensureFolderPathExists(file); + } else if (type == "link") { + // this is linux only ! + auto path = Json::ensureString(meta, "target"); + if (!path.isEmpty()) { + auto target = FS::PathCombine(file, "../" + path); + QFile(target).link(file); + } + } else if (type == "file") { + // TODO download compressed version if it exists ? + auto raw = Json::ensureObject(Json::ensureObject(meta, "downloads"), "raw"); + auto isExec = Json::ensureBoolean(meta, "executable", false); + auto url = Json::ensureString(raw, "url"); + if (!url.isEmpty() && QUrl(url).isValid()) { + auto f = File{ file, url, QByteArray::fromHex(Json::ensureString(raw, "sha1").toLatin1()), isExec }; + toDownload.push_back(f); + } + } + } + auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network()); + for (const auto& file : toDownload) { + auto dl = Net::Download::makeFile(file.url, file.path); + if (!file.hash.isEmpty()) { + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash)); + } + if (file.isExec) { + connect(dl.get(), &Net::Download::succeeded, + [file] { QFile(file.path).setPermissions(QFile(file.path).permissions() | QFileDevice::Permissions(0x1111)); }); + } + elementDownload->addNetAction(dl); + } + connect(elementDownload, &NetJob::finished, [elementDownload, this] { + disconnect(this, &Task::aborted, elementDownload, &NetJob::abort); + elementDownload->deleteLater(); + }); + connect(elementDownload, &NetJob::progress, this, &MojangJavaDownloader::progress); + connect(elementDownload, &NetJob::failed, this, &MojangJavaDownloader::emitFailed); + + connect(this, &Task::aborted, elementDownload, &NetJob::abort); + connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); + elementDownload->start(); +}; diff --git a/launcher/java/providers/MojanglJavaDownloader.h b/launcher/java/providers/MojanglJavaDownloader.h new file mode 100644 index 000000000..a1b5b1765 --- /dev/null +++ b/launcher/java/providers/MojanglJavaDownloader.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "java/providers/BasicJavaDownloader.h" + +class MojangJavaDownloader : public BasicJavaDownloader { + Q_OBJECT + public: + void executeTask() override; + + virtual QString name() const override { return "Mojang"; }; + virtual bool isSupported() const override { return !getOS().isEmpty(); }; + private slots: + void downloadJavaList(); + void parseManifest(const QJsonArray& versionArray); + void downloadJava(const QJsonDocument& doc); + + private: + QString getOS() const; +}; \ No newline at end of file diff --git a/launcher/launch/steps/CheckJava.cpp b/launcher/launch/steps/CheckJava.cpp index 81337a88e..c776092fe 100644 --- a/launcher/launch/steps/CheckJava.cpp +++ b/launcher/launch/steps/CheckJava.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include "java/JavaUtils.h" @@ -90,11 +91,10 @@ void CheckJava::executeTask() // if timestamps are not the same, or something is missing, check! if (m_javaSignature != storedSignature || storedVersion.size() == 0 || storedArchitecture.size() == 0 || storedRealArchitecture.size() == 0 || storedVendor.size() == 0) { - m_JavaChecker.reset(new JavaChecker); + m_JavaChecker.reset(new JavaChecker(realJavaPath, "", 0, 0, 0, 0, this)); emit logLine(QString("Checking Java version..."), MessageLevel::Launcher); connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished); - m_JavaChecker->m_path = realJavaPath; - m_JavaChecker->performCheck(); + m_JavaChecker->start(); return; } else { auto verString = instance->settings()->get("JavaVersion").toString(); @@ -106,10 +106,10 @@ void CheckJava::executeTask() emitSucceeded(); } -void CheckJava::checkJavaFinished(JavaCheckResult result) +void CheckJava::checkJavaFinished(JavaChecker::Result result) { switch (result.validity) { - case JavaCheckResult::Validity::Errored: { + case JavaChecker::Result::Validity::Errored: { // Error message displayed if java can't start emit logLine(QString("Could not start java:"), MessageLevel::Error); emit logLines(result.errorLog.split('\n'), MessageLevel::Error); @@ -117,14 +117,14 @@ void CheckJava::checkJavaFinished(JavaCheckResult result) emitFailed(QString("Could not start java!")); return; } - case JavaCheckResult::Validity::ReturnedInvalidData: { + case JavaChecker::Result::Validity::ReturnedInvalidData: { emit logLine(QString("Java checker returned some invalid data we don't understand:"), MessageLevel::Error); emit logLines(result.outLog.split('\n'), MessageLevel::Warning); emit logLine("\nMinecraft might not start properly.", MessageLevel::Launcher); emitSucceeded(); return; } - case JavaCheckResult::Validity::Valid: { + case JavaChecker::Result::Validity::Valid: { auto instance = m_parent->instance(); printJavaInfo(result.javaVersion.toString(), result.mojangPlatform, result.realPlatform, result.javaVendor); instance->settings()->set("JavaVersion", result.javaVersion.toString()); diff --git a/launcher/launch/steps/CheckJava.h b/launcher/launch/steps/CheckJava.h index 4436e2a55..5ba9e4018 100644 --- a/launcher/launch/steps/CheckJava.h +++ b/launcher/launch/steps/CheckJava.h @@ -28,7 +28,7 @@ class CheckJava : public LaunchStep { virtual void executeTask(); virtual bool canAbort() const { return false; } private slots: - void checkJavaFinished(JavaCheckResult result); + void checkJavaFinished(JavaChecker::Result result); private: void printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString& vendor); @@ -37,5 +37,5 @@ class CheckJava : public LaunchStep { private: QString m_javaPath; QString m_javaSignature; - JavaCheckerPtr m_JavaChecker; + JavaChecker::Ptr m_JavaChecker; }; diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 63d7aa57c..be6b195dc 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -14,7 +14,9 @@ #include "FileSystem.h" #include "JavaCommon.h" #include "JavaDownloader.h" +#include "java/JavaChecker.h" #include "java/JavaInstall.h" +#include "java/JavaInstallList.h" #include "java/JavaUtils.h" #include "ui/dialogs/CustomMessageBox.h" @@ -368,30 +370,25 @@ void JavaSettingsWidget::checkJavaPath(const QString& path) return; } setJavaStatus(JavaStatus::Pending); - m_checker.reset(new JavaChecker()); - m_checker->m_path = path; - m_checker->m_minMem = minHeapSize(); - m_checker->m_maxMem = maxHeapSize(); - if (m_permGenSpinBox->isVisible()) { - m_checker->m_permGen = m_permGenSpinBox->value(); - } + m_checker.reset( + new JavaChecker(path, "", minHeapSize(), maxHeapSize(), m_permGenSpinBox->isVisible() ? m_permGenSpinBox->value() : 0, 0, this)); connect(m_checker.get(), &JavaChecker::checkFinished, this, &JavaSettingsWidget::checkFinished); - m_checker->performCheck(); + m_checker->start(); } -void JavaSettingsWidget::checkFinished(JavaCheckResult result) +void JavaSettingsWidget::checkFinished(JavaChecker::Result result) { m_result = result; switch (result.validity) { - case JavaCheckResult::Validity::Valid: { + case JavaChecker::Result::Validity::Valid: { setJavaStatus(JavaStatus::Good); break; } - case JavaCheckResult::Validity::ReturnedInvalidData: { + case JavaChecker::Result::Validity::ReturnedInvalidData: { setJavaStatus(JavaStatus::ReturnedInvalidData); break; } - case JavaCheckResult::Validity::Errored: { + case JavaChecker::Result::Validity::Errored: { setJavaStatus(JavaStatus::DoesNotStart); break; } diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index 0e05bf341..d3cd2c5a7 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -51,7 +51,7 @@ class JavaSettingsWidget : public QWidget { void on_javaBrowseBtn_clicked(); void on_javaStatusBtn_clicked(); void on_javaDownloadBtn_clicked(); - void checkFinished(JavaCheckResult result); + void checkFinished(JavaChecker::Result result); protected: /* methods */ void checkJavaPathOnEdit(const QString& path); @@ -89,5 +89,5 @@ class JavaSettingsWidget : public QWidget { QString queuedCheck; uint64_t m_availableMemory = 0ull; shared_qobject_ptr m_checker; - JavaCheckResult m_result; + JavaChecker::Result m_result; }; From e89703238365cbcca8cce19b923a28bbb2057516 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 25 Jan 2024 22:22:21 +0200 Subject: [PATCH 024/120] Added java metadata Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 3 +++ launcher/java/JavaVersion.cpp | 20 +++++++++++++++++++ launcher/java/JavaVersion.h | 4 ++++ launcher/minecraft/MojangVersionFormat.cpp | 6 ++++++ launcher/minecraft/OneSixVersionFormat.cpp | 14 +++++++++++++ launcher/minecraft/VersionFile.h | 8 ++++++++ .../ui/pages/instance/InstanceSettingsPage.ui | 2 -- 7 files changed, 55 insertions(+), 2 deletions(-) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index e735f2081..2af33178d 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -430,6 +430,9 @@ set(JAVA_SOURCES java/JavaUtils.cpp java/JavaVersion.h java/JavaVersion.cpp + + java/JavaRuntime.h + java/JavaRuntime.cpp ) set(TRANSLATIONS_SOURCES diff --git a/launcher/java/JavaVersion.cpp b/launcher/java/JavaVersion.cpp index b77bf2adf..3de6f5ad6 100644 --- a/launcher/java/JavaVersion.cpp +++ b/launcher/java/JavaVersion.cpp @@ -109,3 +109,23 @@ bool JavaVersion::operator>(const JavaVersion& rhs) { return (!operator<(rhs)) && (!operator==(rhs)); } + +JavaVersion::JavaVersion(int major, int minor, int security, int build, QString name) + : m_major(major), m_minor(minor), m_security(security), m_name(name), m_parseable(true) +{ + if (build != 0) { + m_prerelease = QString::number(build); + m_string = m_prerelease; + } + if (m_security != 0) + m_string = QString::number(m_security) + "." + m_string; + else if (!m_string.isEmpty()) { + m_string = "0." + m_string; + } + if (m_minor != 0) + m_string = QString::number(m_minor) + "." + m_string; + else if (!m_string.isEmpty()) { + m_string = "0." + m_string; + } + m_string = QString::number(m_major) + "." + m_string; +} diff --git a/launcher/java/JavaVersion.h b/launcher/java/JavaVersion.h index 421578ea1..eee992346 100644 --- a/launcher/java/JavaVersion.h +++ b/launcher/java/JavaVersion.h @@ -16,6 +16,7 @@ class JavaVersion { public: JavaVersion() {} JavaVersion(const QString& rhs); + JavaVersion(int major, int minor, int security, int build = 0, QString name = ""); JavaVersion& operator=(const QString& rhs); @@ -32,12 +33,15 @@ class JavaVersion { int major() { return m_major; } int minor() { return m_minor; } int security() { return m_security; } + QString build() { return m_prerelease; } + QString name() { return m_name; } private: QString m_string; int m_major = 0; int m_minor = 0; int m_security = 0; + QString m_name = ""; bool m_parseable = false; QString m_prerelease; }; diff --git a/launcher/minecraft/MojangVersionFormat.cpp b/launcher/minecraft/MojangVersionFormat.cpp index bb782e47f..d17a3a21f 100644 --- a/launcher/minecraft/MojangVersionFormat.cpp +++ b/launcher/minecraft/MojangVersionFormat.cpp @@ -185,6 +185,9 @@ void MojangVersionFormat::readVersionProperties(const QJsonObject& in, VersionFi out->compatibleJavaMajors.append(requireInteger(compatible)); } } + if (in.contains("compatibleJavaName")) { + out->compatibleJavaName = requireString(in.value("compatibleJavaName")); + } if (in.contains("downloads")) { auto downloadsObj = requireObject(in, "downloads"); @@ -259,6 +262,9 @@ void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObj } out.insert("compatibleJavaMajors", compatibleJavaMajorsOut); } + if (!in->compatibleJavaName.isEmpty()) { + writeString(out, "compatibleJavaName", in->compatibleJavaName); + } } QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr& patch) diff --git a/launcher/minecraft/OneSixVersionFormat.cpp b/launcher/minecraft/OneSixVersionFormat.cpp index 306c95a6a..5f3b4f2a2 100644 --- a/launcher/minecraft/OneSixVersionFormat.cpp +++ b/launcher/minecraft/OneSixVersionFormat.cpp @@ -36,6 +36,8 @@ #include "OneSixVersionFormat.h" #include #include +#include +#include "java/JavaRuntime.h" #include "minecraft/Agent.h" #include "minecraft/ParseUtils.h" @@ -255,6 +257,18 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument& doc out->m_volatile = requireBoolean(root, "volatile"); } + if (root.contains("runtimes")) { + auto runtimes = requireObject(root, "runtimes"); + out->runtimes = {}; + for (auto key : runtimes.keys()) { + QList list; + for (auto runtime : ensureArray(runtimes, key)) { + list.append(JavaRuntime::parseJavaMeta(ensureObject(runtime))); + } + out->runtimes[key] = list; + } + } + /* removed features that shouldn't be used */ if (root.contains("tweakers")) { out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element 'tweakers'")); diff --git a/launcher/minecraft/VersionFile.h b/launcher/minecraft/VersionFile.h index 280e35ee3..297c19709 100644 --- a/launcher/minecraft/VersionFile.h +++ b/launcher/minecraft/VersionFile.h @@ -36,6 +36,8 @@ #pragma once #include +#include +#include #include #include #include @@ -45,6 +47,7 @@ #include "Agent.h" #include "Library.h" #include "ProblemProvider.h" +#include "java/JavaRuntime.h" #include "minecraft/Rule.h" class PackProfile; @@ -98,6 +101,9 @@ class VersionFile : public ProblemContainer { /// Mojang: list of compatible java majors QList compatibleJavaMajors; + /// Mojang: the name of recomended java version + QString compatibleJavaName; + /// Mojang: type of the Minecraft version QString type; @@ -149,6 +155,8 @@ class VersionFile : public ProblemContainer { /// is volatile -- may be removed as soon as it is no longer needed by something else bool m_volatile = false; + QHash> runtimes; + public: // Mojang: DEPRECATED list of 'downloads' - client jar, server jar, windows server exe, maybe more. QMap> mojangDownloads; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index cb37366cc..7762ca8a7 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -796,8 +796,6 @@ enableFeralGamemodeCheck enableMangoHud useDiscreteGpuCheck - modLoaderSettingsGroupBox - disableQuiltBeaconCheckBox gameTimeGroupBox serverJoinGroupBox serverJoinAddress From f36be3f0e3a32cb5f5711a727ecd07cf1c28b8dd Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 25 Jan 2024 22:58:12 +0200 Subject: [PATCH 025/120] Cleanup downloaders Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 4 + launcher/java/JavaRuntime.cpp | 56 ++++++ launcher/java/JavaRuntime.h | 30 ++++ .../ArchiveJavaDownloader.cpp} | 53 ++---- .../ArchiveJavaDownloader.h} | 16 +- .../ManifestJavaDownloader.cpp} | 93 ++-------- .../ManifestJavaDownloader.h} | 20 ++- .../java/providers/AdoptiumJavaDownloader.h | 36 ---- .../java/providers/AzulJavaDownloader.cpp | 159 ------------------ launcher/java/providers/AzulJavaDownloader.h | 37 ---- .../java/providers/BasicJavaDownloader.cpp | 29 ---- 11 files changed, 132 insertions(+), 401 deletions(-) create mode 100644 launcher/java/JavaRuntime.cpp create mode 100644 launcher/java/JavaRuntime.h rename launcher/java/{providers/AdoptiumJavaDownloader.cpp => download/ArchiveJavaDownloader.cpp} (63%) rename launcher/java/{providers/BasicJavaDownloader.h => download/ArchiveJavaDownloader.h} (74%) rename launcher/java/{providers/MojangJavaDownloader.cpp => download/ManifestJavaDownloader.cpp} (55%) rename launcher/java/{providers/MojanglJavaDownloader.h => download/ManifestJavaDownloader.h} (70%) delete mode 100644 launcher/java/providers/AdoptiumJavaDownloader.h delete mode 100644 launcher/java/providers/AzulJavaDownloader.cpp delete mode 100644 launcher/java/providers/AzulJavaDownloader.h delete mode 100644 launcher/java/providers/BasicJavaDownloader.cpp diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 2af33178d..ac3f8eb68 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -433,6 +433,10 @@ set(JAVA_SOURCES java/JavaRuntime.h java/JavaRuntime.cpp + java/download/ArchiveJavaDownloader.cpp + java/download/ArchiveJavaDownloader.h + java/download/ManifestJavaDownloader.cpp + java/download/ManifestJavaDownloader.h ) set(TRANSLATIONS_SOURCES diff --git a/launcher/java/JavaRuntime.cpp b/launcher/java/JavaRuntime.cpp new file mode 100644 index 000000000..0de8c839b --- /dev/null +++ b/launcher/java/JavaRuntime.cpp @@ -0,0 +1,56 @@ +#include "java/JavaRuntime.h" + +#include + +#include "Json.h" +#include "java/JavaVersion.h" +#include "minecraft/ParseUtils.h" + +namespace JavaRuntime { + +DownloadType parseDownloadType(QString javaDownload) +{ + if (javaDownload == "manifest") + return DownloadType::Manifest; + // if (javaDownload == "archive") + return DownloadType::Archive; +} +QString downloadTypeToString(DownloadType javaDownload) +{ + switch (javaDownload) { + case DownloadType::Manifest: + return "manifest"; + case DownloadType::Archive: + return "archive"; + } +} +MetaPtr parseJavaMeta(const QJsonObject& in) +{ + auto meta = std::make_shared(); + + meta->name = Json::ensureString(in, "name", ""); + meta->vendor = Json::ensureString(in, "vendor", ""); + meta->url = Json::ensureString(in, "url", ""); + meta->releaseTime = timeFromS3Time(Json::ensureString(in, "releaseTime", "")); + meta->recommended = Json::ensureBoolean(in, "recommended", false); + meta->downloadType = parseDownloadType(Json::ensureString(in, "downloadType", "")); + meta->packageType = Json::ensureString(in, "packageType", ""); + + if (in.contains("checksum")) { + auto obj = Json::requireObject(in, "checksum"); + meta->checksumHash = Json::ensureString(obj, "hash", ""); + meta->checksumType = Json::ensureString(obj, "type", ""); + } + + if (in.contains("version")) { + auto obj = Json::requireObject(in, "checksum"); + auto name = Json::ensureString(obj, "name", ""); + auto major = Json::ensureInteger(obj, "major", 0); + auto minor = Json::ensureInteger(obj, "minor", 0); + auto security = Json::ensureInteger(obj, "security", 0); + auto build = Json::ensureInteger(obj, "build", 0); + meta->version = JavaVersion(major, minor, security, build, name); + } + return meta; +} +} // namespace JavaRuntime diff --git a/launcher/java/JavaRuntime.h b/launcher/java/JavaRuntime.h new file mode 100644 index 000000000..1ea5d2e48 --- /dev/null +++ b/launcher/java/JavaRuntime.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +#include "java/JavaVersion.h" + +namespace JavaRuntime { + +enum class DownloadType { Manifest, Archive }; + +struct Meta { + QString name; + QString vendor; + QString url; + QDateTime releaseTime; + QString checksumType; + QString checksumHash; + bool recommended; + DownloadType downloadType; + QString packageType; + JavaVersion version; +}; +using MetaPtr = std::shared_ptr; + +DownloadType parseDownloadType(QString javaDownload); +QString downloadTypeToString(DownloadType javaDownload); +MetaPtr parseJavaMeta(const QJsonObject& libObj); + +} // namespace JavaRuntime \ No newline at end of file diff --git a/launcher/java/providers/AdoptiumJavaDownloader.cpp b/launcher/java/download/ArchiveJavaDownloader.cpp similarity index 63% rename from launcher/java/providers/AdoptiumJavaDownloader.cpp rename to launcher/java/download/ArchiveJavaDownloader.cpp index 4f8499d4a..844be1dce 100644 --- a/launcher/java/providers/AdoptiumJavaDownloader.cpp +++ b/launcher/java/download/ArchiveJavaDownloader.cpp @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "java/providers/AdoptiumJavaDownloader.h" +#include "java/download/ArchiveJavaDownloader.h" #include #include #include "MMCZip.h" @@ -24,39 +24,21 @@ #include "net/NetJob.h" #include "tasks/Task.h" -void AdoptiumJavaDownloader::executeTask() -{ - downloadJava(); -}; - -QString AdoptiumJavaDownloader::getArch() const -{ - if (m_os_arch == "arm64") - return "aarch64"; - if (m_os_arch.isEmpty()) - return "x86"; - return m_os_arch; -} - -void AdoptiumJavaDownloader::downloadJava() +void ArchiveJavaDownloader::executeTask() { // JRE found ! download the zip - setStatus(tr("Downloading Java from Adoptium")); + setStatus(tr("Downloading Java")); - auto javaVersion = m_is_legacy ? QString("8") : QString("17"); - auto azulOS = m_os_name == "osx" ? "mac" : m_os_name; - auto arch = getArch(); - MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("java", "adoptiumJRE.zip"); + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("java", m_url.toLocalFile()); auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); - download->addNetAction(Net::Download::makeCached( - QString("https://api.adoptium.net/v3/binary/latest/%1/ga/%2/%3/jre/hotspot/normal/eclipse").arg(javaVersion, azulOS, arch), entry)); + download->addNetAction(Net::Download::makeCached(m_url, entry)); auto fullPath = entry->getFullPath(); connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); // connect(download.get(), &NetJob::aborted, [path] { APPLICATION->instances()->destroyStagingPath(path); }); - connect(download.get(), &NetJob::progress, this, &AdoptiumJavaDownloader::progress); - connect(download.get(), &NetJob::failed, this, &AdoptiumJavaDownloader::emitFailed); + connect(download.get(), &NetJob::progress, this, &ArchiveJavaDownloader::progress); + connect(download.get(), &NetJob::failed, this, &ArchiveJavaDownloader::emitFailed); connect(this, &Task::aborted, download.get(), &NetJob::abort); connect(download.get(), &NetJob::succeeded, [this, fullPath] { // This should do all of the extracting and creating folders @@ -65,7 +47,7 @@ void AdoptiumJavaDownloader::downloadJava() download->start(); }; -void AdoptiumJavaDownloader::extractJava(QString input) +void ArchiveJavaDownloader::extractJava(QString input) { setStatus(tr("Extracting java")); auto zip = std::make_shared(input); @@ -85,14 +67,14 @@ void AdoptiumJavaDownloader::extractJava(QString input) connect(this, &Task::aborted, zipTask.get(), &Task::abort); connect(zipTask.get(), &Task::finished, [zipTask, this] { disconnect(this, &Task::aborted, zipTask.get(), &Task::abort); }); - connect(zipTask.get(), &Task::succeeded, this, &AdoptiumJavaDownloader::emitSucceeded); - connect(zipTask.get(), &Task::aborted, this, &AdoptiumJavaDownloader::emitAborted); + connect(zipTask.get(), &Task::succeeded, this, &ArchiveJavaDownloader::emitSucceeded); + connect(zipTask.get(), &Task::aborted, this, &ArchiveJavaDownloader::emitAborted); connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) { progressStep->state = TaskStepState::Failed; stepProgress(*progressStep); emitFailed(reason); }); - connect(zipTask.get(), &Task::stepProgress, this, &AdoptiumJavaDownloader::propagateStepProgress); + connect(zipTask.get(), &Task::stepProgress, this, &ArchiveJavaDownloader::propagateStepProgress); connect(zipTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { progressStep->update(current, total); @@ -104,16 +86,3 @@ void AdoptiumJavaDownloader::extractJava(QString input) }); zipTask->start(); }; - -static const QStringList supportedOs = { - "linux", "windows", "mac", "solaris", "aix", "alpine-linux", -}; - -static const QStringList supportedArch = { - "x64", "x86", "x32", "ppc64", "ppc64le", "s390x", "aarch64", "arm", "sparcv9", "riscv64", -}; - -bool AdoptiumJavaDownloader::isSupported() const -{ - return supportedOs.contains(m_os_name == "osx" ? "mac" : m_os_name) && supportedArch.contains(getArch()); -}; \ No newline at end of file diff --git a/launcher/java/providers/BasicJavaDownloader.h b/launcher/java/download/ArchiveJavaDownloader.h similarity index 74% rename from launcher/java/providers/BasicJavaDownloader.h rename to launcher/java/download/ArchiveJavaDownloader.h index 34c944ec8..d17657086 100644 --- a/launcher/java/providers/BasicJavaDownloader.h +++ b/launcher/java/download/ArchiveJavaDownloader.h @@ -18,24 +18,24 @@ #pragma once +#include #include "tasks/Task.h" -class BasicJavaDownloader : public Task { +class ArchiveJavaDownloader : public Task { Q_OBJECT public: - BasicJavaDownloader(QString final_path, bool m_is_legacy = false, QObject* parent = nullptr); - virtual ~BasicJavaDownloader() = default; + ArchiveJavaDownloader(QUrl url, QString final_path); + virtual ~ArchiveJavaDownloader() = default; [[nodiscard]] bool canAbort() const override { return true; } + void executeTask() override; - virtual QString name() const = 0; - virtual bool isSupported() const = 0; + private slots: + void extractJava(QString input); protected: - QString m_os_name; - QString m_os_arch; + QUrl m_url; QString m_final_path; - bool m_is_legacy; Task::Ptr m_current_task; }; \ No newline at end of file diff --git a/launcher/java/providers/MojangJavaDownloader.cpp b/launcher/java/download/ManifestJavaDownloader.cpp similarity index 55% rename from launcher/java/providers/MojangJavaDownloader.cpp rename to launcher/java/download/ManifestJavaDownloader.cpp index fc2a17e94..4f7dab94e 100644 --- a/launcher/java/providers/MojangJavaDownloader.cpp +++ b/launcher/java/download/ManifestJavaDownloader.cpp @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "java/providers/MojanglJavaDownloader.h" +#include "java/download/ManifestJavaDownloader.h" #include "Application.h" #include "FileSystem.h" @@ -30,89 +30,18 @@ struct File { bool isExec; }; -void MojangJavaDownloader::executeTask() +ManifestJavaDownloader::ManifestJavaDownloader(QUrl url, QString final_path) : m_url(url), m_final_path(final_path){}; +void ManifestJavaDownloader::executeTask() { - downloadJavaList(); -}; - -void MojangJavaDownloader::downloadJavaList() -{ - auto netJob = makeShared(QString("JRE::QueryVersions"), APPLICATION->network()); - auto response = std::make_shared(); - setStatus(tr("Querying mojang meta")); - netJob->addNetAction(Net::Download::makeByteArray( - QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); - - connect(netJob.get(), &NetJob::finished, [netJob, this] { - // delete so that it's not called on a deleted job - // FIXME: is this needed? qt should handle this - disconnect(this, &Task::aborted, netJob.get(), &NetJob::abort); - }); - connect(this, &Task::aborted, netJob.get(), &NetJob::abort); - - connect(netJob.get(), &NetJob::progress, this, &MojangJavaDownloader::progress); - connect(netJob.get(), &NetJob::failed, this, &MojangJavaDownloader::emitFailed); - connect(netJob.get(), &NetJob::succeeded, [response, this, netJob] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *response; - emitFailed(parse_error.errorString()); - return; - } - auto versionArray = Json::ensureArray(Json::ensureObject(doc.object(), getOS()), m_is_legacy ? "jre-legacy" : "java-runtime-gamma"); - if (!versionArray.empty()) { - parseManifest(versionArray); - - } else { - // mojang does not have a JRE for us, so fail - emitFailed("No suitable JRE found"); - } - }); - - netJob->start(); -}; - -QString MojangJavaDownloader::getOS() const -{ - if (m_os_name == "windows") { - if (m_os_arch == "x86_64") { - return "windows-x64"; - } - if (m_os_arch == "i386") { - return "windows-x86"; - } - // Unknown, maybe arm, appending arch for downloader - return "windows-" + m_os_arch; - } - if (m_os_name == "osx") { - if (m_os_arch == "arm64") { - return "mac-os-arm64"; - } - return "mac-os"; - } - if (m_os_name == "linux") { - if (m_os_arch == "x86_64") { - return "linux"; - } - // will work for i386, and arm(64) - return "linux-" + m_os_arch; - } - return {}; -} -void MojangJavaDownloader::parseManifest(const QJsonArray& versionArray) -{ - setStatus(tr("Downloading Java from Mojang")); - auto url = Json::ensureString(Json::ensureObject(Json::ensureObject(versionArray[0]), "manifest"), "url"); + setStatus(tr("Downloading Java")); auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); auto files = std::make_shared(); - download->addNetAction(Net::Download::makeByteArray(QUrl(url), files)); + download->addNetAction(Net::Download::makeByteArray(m_url, files)); connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); - connect(download.get(), &NetJob::progress, this, &MojangJavaDownloader::progress); - connect(download.get(), &NetJob::failed, this, &MojangJavaDownloader::emitFailed); + connect(download.get(), &NetJob::progress, this, &ManifestJavaDownloader::progress); + connect(download.get(), &NetJob::failed, this, &ManifestJavaDownloader::emitFailed); connect(this, &Task::aborted, download.get(), &NetJob::abort); connect(download.get(), &NetJob::succeeded, [files, this] { @@ -129,7 +58,7 @@ void MojangJavaDownloader::parseManifest(const QJsonArray& versionArray) download->start(); }; -void MojangJavaDownloader::downloadJava(const QJsonDocument& doc) +void ManifestJavaDownloader::downloadJava(const QJsonDocument& doc) { // valid json doc, begin making jre spot FS::ensureFolderPathExists(m_final_path); @@ -176,10 +105,10 @@ void MojangJavaDownloader::downloadJava(const QJsonDocument& doc) disconnect(this, &Task::aborted, elementDownload, &NetJob::abort); elementDownload->deleteLater(); }); - connect(elementDownload, &NetJob::progress, this, &MojangJavaDownloader::progress); - connect(elementDownload, &NetJob::failed, this, &MojangJavaDownloader::emitFailed); + connect(elementDownload, &NetJob::progress, this, &ManifestJavaDownloader::progress); + connect(elementDownload, &NetJob::failed, this, &ManifestJavaDownloader::emitFailed); connect(this, &Task::aborted, elementDownload, &NetJob::abort); connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); elementDownload->start(); -}; +}; \ No newline at end of file diff --git a/launcher/java/providers/MojanglJavaDownloader.h b/launcher/java/download/ManifestJavaDownloader.h similarity index 70% rename from launcher/java/providers/MojanglJavaDownloader.h rename to launcher/java/download/ManifestJavaDownloader.h index a1b5b1765..44e9ed9de 100644 --- a/launcher/java/providers/MojanglJavaDownloader.h +++ b/launcher/java/download/ManifestJavaDownloader.h @@ -18,20 +18,24 @@ #pragma once -#include "java/providers/BasicJavaDownloader.h" +#include +#include "tasks/Task.h" -class MojangJavaDownloader : public BasicJavaDownloader { +class ManifestJavaDownloader : public Task { Q_OBJECT public: + ManifestJavaDownloader(QUrl url, QString final_path); + virtual ~ManifestJavaDownloader() = default; + + [[nodiscard]] bool canAbort() const override { return true; } void executeTask() override; - virtual QString name() const override { return "Mojang"; }; - virtual bool isSupported() const override { return !getOS().isEmpty(); }; private slots: - void downloadJavaList(); - void parseManifest(const QJsonArray& versionArray); void downloadJava(const QJsonDocument& doc); - private: - QString getOS() const; + protected: + QUrl m_url; + QString m_final_path; + + Task::Ptr m_current_task; }; \ No newline at end of file diff --git a/launcher/java/providers/AdoptiumJavaDownloader.h b/launcher/java/providers/AdoptiumJavaDownloader.h deleted file mode 100644 index f0ae6239b..000000000 --- a/launcher/java/providers/AdoptiumJavaDownloader.h +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "java/providers/BasicJavaDownloader.h" - -class AdoptiumJavaDownloader : public BasicJavaDownloader { - Q_OBJECT - public: - void executeTask() override; - - virtual QString name() const override { return "Adoptium"; }; - virtual bool isSupported() const override; - private slots: - void downloadJava(); - void extractJava(QString input); - - private: - QString getArch() const; -}; \ No newline at end of file diff --git a/launcher/java/providers/AzulJavaDownloader.cpp b/launcher/java/providers/AzulJavaDownloader.cpp deleted file mode 100644 index 674da592e..000000000 --- a/launcher/java/providers/AzulJavaDownloader.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "java/providers/AzulJavaDownloader.h" -#include -#include "MMCZip.h" - -#include "Application.h" -#include "Json.h" -#include "net/NetJob.h" -#include "tasks/Task.h" - -void AzulJavaDownloader::executeTask() -{ - downloadJavaList(); -}; - -void AzulJavaDownloader::downloadJavaList() -{ - setStatus(tr("Querying Azul meta")); - - auto javaVersion = m_is_legacy ? QString("8.0") : QString("17.0"); - auto azulOS = m_os_name == "osx" ? "macos" : m_os_name; - auto arch = getArch(); - auto metaResponse = std::make_shared(); - auto downloadJob = makeShared(QString("JRE::QueryAzulMeta"), APPLICATION->network()); - downloadJob->addNetAction(Net::Download::makeByteArray(QString("https://api.azul.com/metadata/v1/zulu/packages/?" - "java_version=%1" - "&os=%2" - "&arch=%3" - "&archive_type=zip" - "&java_package_type=jre" - "&support_term=lts" - "&latest=true" - "status=ga" - "&availability_types=CA" - "&page=1" - "&page_size=1") - .arg(javaVersion, azulOS, arch), - metaResponse)); - connect(downloadJob.get(), &NetJob::finished, - [downloadJob, metaResponse, this] { disconnect(this, &Task::aborted, downloadJob.get(), &NetJob::abort); }); - connect(this, &Task::aborted, downloadJob.get(), &NetJob::abort); - connect(downloadJob.get(), &NetJob::failed, this, &AzulJavaDownloader::emitFailed); - connect(downloadJob.get(), &NetJob::progress, this, &AzulJavaDownloader::progress); - connect(downloadJob.get(), &NetJob::succeeded, [metaResponse, this] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *metaResponse; - return; - } - auto array = Json::ensureArray(doc.array()); - if (!array.empty()) { - downloadJava(array); - } else { - emitFailed(tr("No suitable JRE found")); - } - }); - downloadJob->start(); -}; - -QString AzulJavaDownloader::getArch() const -{ - if (m_os_arch == "arm64") - return "aarch64"; - if (m_os_arch == "arm") - return "aarch32"; - if (m_os_arch.isEmpty()) - return "x86"; - return m_os_arch; -} - -void AzulJavaDownloader::downloadJava(const QJsonArray& array) -{ - // JRE found ! download the zip - setStatus(tr("Downloading Java from Azul")); - - MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("java", "azulJRE.zip"); - - auto downloadURL = QUrl(array[0].toObject()["url"].toString()); - auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); - download->addNetAction(Net::Download::makeCached(downloadURL, entry)); - auto fullPath = entry->getFullPath(); - - connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); - // connect(download.get(), &NetJob::aborted, [path] { APPLICATION->instances()->destroyStagingPath(path); }); - connect(download.get(), &NetJob::progress, this, &AzulJavaDownloader::progress); - connect(download.get(), &NetJob::failed, this, &AzulJavaDownloader::emitFailed); - connect(this, &Task::aborted, download.get(), &NetJob::abort); - connect(download.get(), &NetJob::succeeded, [downloadURL, this, fullPath] { - // This should do all of the extracting and creating folders - extractJava(fullPath, downloadURL.fileName().chopped(4)); - }); - download->start(); -}; - -void AzulJavaDownloader::extractJava(QString input, QString subdirectory) -{ - setStatus(tr("Extracting java")); - auto zipTask = makeShared(input, m_final_path, subdirectory); - - auto progressStep = std::make_shared(); - connect(zipTask.get(), &Task::finished, this, [this, progressStep] { - progressStep->state = TaskStepState::Succeeded; - stepProgress(*progressStep); - }); - - connect(this, &Task::aborted, zipTask.get(), &Task::abort); - connect(zipTask.get(), &Task::finished, [zipTask, this] { disconnect(this, &Task::aborted, zipTask.get(), &Task::abort); }); - - connect(zipTask.get(), &Task::succeeded, this, &AzulJavaDownloader::emitSucceeded); - connect(zipTask.get(), &Task::aborted, this, &AzulJavaDownloader::emitAborted); - connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) { - progressStep->state = TaskStepState::Failed; - stepProgress(*progressStep); - emitFailed(reason); - }); - connect(zipTask.get(), &Task::stepProgress, this, &AzulJavaDownloader::propagateStepProgress); - - connect(zipTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { - progressStep->update(current, total); - stepProgress(*progressStep); - }); - connect(zipTask.get(), &Task::status, this, [this, progressStep](QString status) { - progressStep->status = status; - stepProgress(*progressStep); - }); - zipTask->start(); -}; - -static const QStringList supportedOs = { - "macos", "linux", "windows", "linux-musl", "linux-glibc", "qnx", "solaris", "aix", -}; - -static const QStringList supportedArch = { - "x86", "x64", "amd64", "i686", "arm", "aarch64", "aarch32", "aarch32sf", "aarch32hf", "ppc", - "ppc64", "ppc32", "ppc32hf", "ppc32spe", "sparc", "sparc64", "sparc32", "sparcv9", "sparcv9-64", "sparcv9-32", -}; - -bool AzulJavaDownloader::isSupported() const -{ - return supportedOs.contains(m_os_name == "osx" ? "macos" : m_os_name) && supportedArch.contains(getArch()); -}; \ No newline at end of file diff --git a/launcher/java/providers/AzulJavaDownloader.h b/launcher/java/providers/AzulJavaDownloader.h deleted file mode 100644 index c4bc8c761..000000000 --- a/launcher/java/providers/AzulJavaDownloader.h +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "java/providers/BasicJavaDownloader.h" - -class AzulJavaDownloader : public BasicJavaDownloader { - Q_OBJECT - public: - void executeTask() override; - - virtual QString name() const override { return "Azul"; }; - virtual bool isSupported() const override; - private slots: - void downloadJavaList(); - void downloadJava(const QJsonArray& doc); - void extractJava(QString input, QString subdirectory); - - private: - QString getArch() const; -}; \ No newline at end of file diff --git a/launcher/java/providers/BasicJavaDownloader.cpp b/launcher/java/providers/BasicJavaDownloader.cpp deleted file mode 100644 index 9f353d9c1..000000000 --- a/launcher/java/providers/BasicJavaDownloader.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "java/providers/BasicJavaDownloader.h" - -#include "SysInfo.h" -#include "tasks/Task.h" - -BasicJavaDownloader::BasicJavaDownloader(QString final_path, bool m_is_legacy, QObject* parent) - : Task(parent) - , m_os_name(SysInfo::currentSystem()) - , m_os_arch(SysInfo::useQTForArch()) - , m_final_path(final_path) - , m_is_legacy(m_is_legacy) -{} From 81282bf7e0189ede29d2db14f85ef2c886d8b583 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 26 Jan 2024 00:22:05 +0200 Subject: [PATCH 026/120] Autodetect Java? Signed-off-by: Trial97 --- launcher/java/JavaRuntime.cpp | 19 +++++++ launcher/java/JavaRuntime.h | 19 +++++++ launcher/java/JavaUtils.cpp | 1 + .../java/download/ArchiveJavaDownloader.cpp | 18 +++++-- .../java/download/ArchiveJavaDownloader.h | 4 +- .../java/download/ManifestJavaDownloader.cpp | 18 +++++-- .../java/download/ManifestJavaDownloader.h | 4 +- .../minecraft/launch/VerifyJavaInstall.cpp | 49 ++++++++++++++----- 8 files changed, 112 insertions(+), 20 deletions(-) diff --git a/launcher/java/JavaRuntime.cpp b/launcher/java/JavaRuntime.cpp index 0de8c839b..78651e991 100644 --- a/launcher/java/JavaRuntime.cpp +++ b/launcher/java/JavaRuntime.cpp @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "java/JavaRuntime.h" #include @@ -23,6 +41,7 @@ QString downloadTypeToString(DownloadType javaDownload) case DownloadType::Archive: return "archive"; } + return ""; } MetaPtr parseJavaMeta(const QJsonObject& in) { diff --git a/launcher/java/JavaRuntime.h b/launcher/java/JavaRuntime.h index 1ea5d2e48..b44b546b6 100644 --- a/launcher/java/JavaRuntime.h +++ b/launcher/java/JavaRuntime.h @@ -1,8 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #pragma once #include #include +#include + #include "java/JavaVersion.h" namespace JavaRuntime { diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 074bf54df..67f1fd3a7 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -393,6 +393,7 @@ QList JavaUtils::FindJavaPaths() scanJavaDir(snap + dirPath); } }; + scanJavaDir(FS::PathCombine(APPLICATION->dataRoot(), "java")); // oracle RPMs scanJavaDirs("/usr/java"); // general locations used by distro packaging diff --git a/launcher/java/download/ArchiveJavaDownloader.cpp b/launcher/java/download/ArchiveJavaDownloader.cpp index 844be1dce..32a3c39d2 100644 --- a/launcher/java/download/ArchiveJavaDownloader.cpp +++ b/launcher/java/download/ArchiveJavaDownloader.cpp @@ -21,9 +21,13 @@ #include "MMCZip.h" #include "Application.h" +#include "net/ChecksumValidator.h" #include "net/NetJob.h" #include "tasks/Task.h" +ArchiveJavaDownloader::ArchiveJavaDownloader(QUrl url, QString final_path, QString checksumType, QString checksumHash) + : m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash){}; + void ArchiveJavaDownloader::executeTask() { // JRE found ! download the zip @@ -32,7 +36,15 @@ void ArchiveJavaDownloader::executeTask() MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("java", m_url.toLocalFile()); auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); - download->addNetAction(Net::Download::makeCached(m_url, entry)); + auto action = Net::Download::makeCached(m_url, entry); + if (!m_checksum_hash.isEmpty() && !m_checksum_type.isEmpty()) { + auto hashType = QCryptographicHash::Algorithm::Sha1; + if (m_checksum_type == "sha256") { + hashType = QCryptographicHash::Algorithm::Sha256; + } + action->addValidator(new Net::ChecksumValidator(hashType, m_checksum_hash.toLatin1())); + } + download->addNetAction(action); auto fullPath = entry->getFullPath(); connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); @@ -45,7 +57,7 @@ void ArchiveJavaDownloader::executeTask() extractJava(fullPath); }); download->start(); -}; +} void ArchiveJavaDownloader::extractJava(QString input) { @@ -85,4 +97,4 @@ void ArchiveJavaDownloader::extractJava(QString input) stepProgress(*progressStep); }); zipTask->start(); -}; +} \ No newline at end of file diff --git a/launcher/java/download/ArchiveJavaDownloader.h b/launcher/java/download/ArchiveJavaDownloader.h index d17657086..230f62b4d 100644 --- a/launcher/java/download/ArchiveJavaDownloader.h +++ b/launcher/java/download/ArchiveJavaDownloader.h @@ -24,7 +24,7 @@ class ArchiveJavaDownloader : public Task { Q_OBJECT public: - ArchiveJavaDownloader(QUrl url, QString final_path); + ArchiveJavaDownloader(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = ""); virtual ~ArchiveJavaDownloader() = default; [[nodiscard]] bool canAbort() const override { return true; } @@ -36,6 +36,8 @@ class ArchiveJavaDownloader : public Task { protected: QUrl m_url; QString m_final_path; + QString m_checksum_type; + QString m_checksum_hash; Task::Ptr m_current_task; }; \ No newline at end of file diff --git a/launcher/java/download/ManifestJavaDownloader.cpp b/launcher/java/download/ManifestJavaDownloader.cpp index 4f7dab94e..08321ca7f 100644 --- a/launcher/java/download/ManifestJavaDownloader.cpp +++ b/launcher/java/download/ManifestJavaDownloader.cpp @@ -30,14 +30,24 @@ struct File { bool isExec; }; -ManifestJavaDownloader::ManifestJavaDownloader(QUrl url, QString final_path) : m_url(url), m_final_path(final_path){}; +ManifestJavaDownloader::ManifestJavaDownloader(QUrl url, QString final_path, QString checksumType, QString checksumHash) + : m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash){}; + void ManifestJavaDownloader::executeTask() { setStatus(tr("Downloading Java")); auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); auto files = std::make_shared(); - download->addNetAction(Net::Download::makeByteArray(m_url, files)); + auto action = Net::Download::makeByteArray(m_url, files); + if (!m_checksum_hash.isEmpty() && !m_checksum_type.isEmpty()) { + auto hashType = QCryptographicHash::Algorithm::Sha1; + if (m_checksum_type == "sha256") { + hashType = QCryptographicHash::Algorithm::Sha256; + } + action->addValidator(new Net::ChecksumValidator(hashType, m_checksum_hash.toLatin1())); + } + download->addNetAction(action); connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); connect(download.get(), &NetJob::progress, this, &ManifestJavaDownloader::progress); @@ -56,7 +66,7 @@ void ManifestJavaDownloader::executeTask() downloadJava(doc); }); download->start(); -}; +} void ManifestJavaDownloader::downloadJava(const QJsonDocument& doc) { @@ -111,4 +121,4 @@ void ManifestJavaDownloader::downloadJava(const QJsonDocument& doc) connect(this, &Task::aborted, elementDownload, &NetJob::abort); connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); elementDownload->start(); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/launcher/java/download/ManifestJavaDownloader.h b/launcher/java/download/ManifestJavaDownloader.h index 44e9ed9de..d7114f4bd 100644 --- a/launcher/java/download/ManifestJavaDownloader.h +++ b/launcher/java/download/ManifestJavaDownloader.h @@ -24,7 +24,7 @@ class ManifestJavaDownloader : public Task { Q_OBJECT public: - ManifestJavaDownloader(QUrl url, QString final_path); + ManifestJavaDownloader(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = ""); virtual ~ManifestJavaDownloader() = default; [[nodiscard]] bool canAbort() const override { return true; } @@ -36,6 +36,8 @@ class ManifestJavaDownloader : public Task { protected: QUrl m_url; QString m_final_path; + QString m_checksum_type; + QString m_checksum_hash; Task::Ptr m_current_task; }; \ No newline at end of file diff --git a/launcher/minecraft/launch/VerifyJavaInstall.cpp b/launcher/minecraft/launch/VerifyJavaInstall.cpp index cdd1f7fd1..218811290 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.cpp +++ b/launcher/minecraft/launch/VerifyJavaInstall.cpp @@ -34,7 +34,11 @@ */ #include "VerifyJavaInstall.h" +#include +#include "Application.h" +#include "java/JavaInstall.h" +#include "java/JavaInstallList.h" #include "java/JavaVersion.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" @@ -46,6 +50,7 @@ void VerifyJavaInstall::executeTask() auto settings = instance->settings(); auto storedVersion = settings->get("JavaVersion").toString(); auto ignoreCompatibility = settings->get("IgnoreJavaCompatibility").toBool(); + auto automaticJavaSwitch = settings->get("AutomaticJavaSwitch").toBool(); auto compatibleMajors = packProfile->getProfile()->getCompatibleJavaMajors(); @@ -62,16 +67,38 @@ void VerifyJavaInstall::executeTask() 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); + auto logFail = [this, &javaVersion, compatibleMajors] { + 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")); + emitFailed(QString("Incompatible Java major version")); + }; + + if (automaticJavaSwitch || true) { + settings->set("OverrideJava", true); + auto javas = APPLICATION->javalist().get(); + auto task = javas->getLoadTask(); + connect(task.get(), &Task::finished, this, [this, javas, compatibleMajors, settings, &logFail] { + for (auto i = 0; i < javas->count(); i++) { + auto java = std::dynamic_pointer_cast(javas->at(i)); + if (java && compatibleMajors.contains(java->id.major())) { + settings->set("OverrideJavaLocation", true); + settings->set("JavaPath", java->path); + emitSucceeded(); + return; + } + } + logFail(); + }); + } else { + logFail(); + } } From 4cd236ed807e44666e6775126d27fef237eef168 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 26 Jan 2024 00:31:43 +0200 Subject: [PATCH 027/120] missing header Signed-off-by: Trial97 --- launcher/java/JavaChecker.cpp | 3 ++- launcher/java/JavaRuntime.h | 1 + launcher/java/download/ArchiveJavaDownloader.cpp | 3 ++- launcher/java/download/ManifestJavaDownloader.cpp | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index 7271c0d09..18f93d256 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -44,7 +44,8 @@ #include "java/JavaUtils.h" JavaChecker::JavaChecker(QString path, QString args, int minMem, int maxMem, int permGen, int id, QObject* parent) - : Task(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen), m_id(id){}; + : Task(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen), m_id(id) +{} void JavaChecker::executeTask() { diff --git a/launcher/java/JavaRuntime.h b/launcher/java/JavaRuntime.h index b44b546b6..4c4efa288 100644 --- a/launcher/java/JavaRuntime.h +++ b/launcher/java/JavaRuntime.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include diff --git a/launcher/java/download/ArchiveJavaDownloader.cpp b/launcher/java/download/ArchiveJavaDownloader.cpp index 32a3c39d2..5350fc4e6 100644 --- a/launcher/java/download/ArchiveJavaDownloader.cpp +++ b/launcher/java/download/ArchiveJavaDownloader.cpp @@ -26,7 +26,8 @@ #include "tasks/Task.h" ArchiveJavaDownloader::ArchiveJavaDownloader(QUrl url, QString final_path, QString checksumType, QString checksumHash) - : m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash){}; + : m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash) +{} void ArchiveJavaDownloader::executeTask() { diff --git a/launcher/java/download/ManifestJavaDownloader.cpp b/launcher/java/download/ManifestJavaDownloader.cpp index 08321ca7f..368d6431c 100644 --- a/launcher/java/download/ManifestJavaDownloader.cpp +++ b/launcher/java/download/ManifestJavaDownloader.cpp @@ -31,7 +31,8 @@ struct File { }; ManifestJavaDownloader::ManifestJavaDownloader(QUrl url, QString final_path, QString checksumType, QString checksumHash) - : m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash){}; + : m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash) +{} void ManifestJavaDownloader::executeTask() { From 7317105e4d8c7a65f4a722dbebf8d5e3247f80dc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 27 Jan 2024 22:47:28 +0200 Subject: [PATCH 028/120] Code spaghetti and more chaos Signed-off-by: Trial97 --- launcher/BaseVersionList.cpp | 1 + launcher/BaseVersionList.h | 1 + launcher/CMakeLists.txt | 8 +- launcher/JavaDownloader.cpp | 332 ------------------ launcher/JavaDownloader.h | 28 -- launcher/SysInfo.cpp | 43 ++- launcher/SysInfo.h | 1 + launcher/VersionProxyModel.cpp | 9 + launcher/VersionProxyModel.h | 2 +- launcher/java/JavaRuntime.cpp | 2 +- launcher/java/JavaVersion.cpp | 21 +- .../java/download/ArchiveJavaDownloader.cpp | 2 +- .../java/download/ManifestJavaDownloader.cpp | 2 +- launcher/ui/java/JavaDownload.cpp | 103 ++++++ launcher/ui/java/JavaDownload.h | 48 +++ launcher/ui/java/JavaDownload.ui | 100 ++++++ launcher/ui/java/ListModel.cpp | 154 ++++++++ launcher/ui/java/ListModel.h | 132 +++++++ launcher/ui/pages/global/JavaPage.cpp | 5 +- .../pages/instance/InstanceSettingsPage.cpp | 5 +- launcher/ui/widgets/JavaSettingsWidget.cpp | 5 +- 21 files changed, 613 insertions(+), 391 deletions(-) delete mode 100644 launcher/JavaDownloader.cpp delete mode 100644 launcher/JavaDownloader.h create mode 100644 launcher/ui/java/JavaDownload.cpp create mode 100644 launcher/ui/java/JavaDownload.h create mode 100644 launcher/ui/java/JavaDownload.ui create mode 100644 launcher/ui/java/ListModel.cpp create mode 100644 launcher/ui/java/ListModel.h diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp index e11560d5e..576c3a413 100644 --- a/launcher/BaseVersionList.cpp +++ b/launcher/BaseVersionList.cpp @@ -110,6 +110,7 @@ QHash BaseVersionList::roleNames() const roles.insert(TypeRole, "type"); roles.insert(BranchRole, "branch"); roles.insert(PathRole, "path"); + roles.insert(AliasRole, "alias"); roles.insert(ArchitectureRole, "architecture"); return roles; } diff --git a/launcher/BaseVersionList.h b/launcher/BaseVersionList.h index 231887c4e..c59d70570 100644 --- a/launcher/BaseVersionList.h +++ b/launcher/BaseVersionList.h @@ -48,6 +48,7 @@ class BaseVersionList : public QAbstractListModel { TypeRole, BranchRole, PathRole, + AliasRole, ArchitectureRole, SortRole }; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ac3f8eb68..d703b8263 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -437,6 +437,11 @@ set(JAVA_SOURCES java/download/ArchiveJavaDownloader.h java/download/ManifestJavaDownloader.cpp java/download/ManifestJavaDownloader.h + + ui/java/JavaDownload.h + ui/java/JavaDownload.cpp + ui/java/ListModel.h + ui/java/ListModel.cpp ) set(TRANSLATIONS_SOURCES @@ -1107,8 +1112,6 @@ SET(LAUNCHER_SOURCES ui/instanceview/InstanceDelegate.h ui/instanceview/VisualGroup.cpp ui/instanceview/VisualGroup.h - JavaDownloader.cpp - JavaDownloader.h ) if (NOT Apple) @@ -1189,6 +1192,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ScrollMessageBox.ui ui/dialogs/BlockedModsDialog.ui ui/dialogs/ChooseProviderDialog.ui + ui/java/JavaDownload.ui ) qt_wrap_ui(PRISM_UPDATE_UI diff --git a/launcher/JavaDownloader.cpp b/launcher/JavaDownloader.cpp deleted file mode 100644 index e4f4b5f09..000000000 --- a/launcher/JavaDownloader.cpp +++ /dev/null @@ -1,332 +0,0 @@ -#include "JavaDownloader.h" -#include -#include -#include -#include -#include "Application.h" -#include "FileSystem.h" -#include "InstanceList.h" -#include "Json.h" -#include "MMCZip.h" -#include "SysInfo.h" -#include "net/ChecksumValidator.h" -#include "net/NetJob.h" -#include "ui/dialogs/ProgressDialog.h" - -// Quick & dirty struct to store files -struct File { - QString path; - QString url; - QByteArray hash; - bool isExec; -}; - -void JavaDownloader::executeTask() -{ - auto OS = m_OS; - auto isLegacy = m_isLegacy; - - downloadMojangJavaList(OS, isLegacy); -} -void JavaDownloader::downloadMojangJavaList(const QString& OS, bool isLegacy) -{ - auto netJob = makeShared(QString("JRE::QueryVersions"), APPLICATION->network()); - auto response = std::make_shared(); - setStatus(tr("Querying mojang meta")); - netJob->addNetAction(Net::Download::makeByteArray( - QUrl("https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"), response)); - - connect(this, &Task::aborted, [isLegacy] { - QDir(FS::PathCombine(QCoreApplication::applicationDirPath(), "java", (isLegacy ? "java-legacy" : "java-current"))) - .removeRecursively(); - }); - - connect(netJob.get(), &NetJob::finished, [netJob, response, this] { - // delete so that it's not called on a deleted job - // FIXME: is this needed? qt should handle this - disconnect(this, &Task::aborted, netJob.get(), &NetJob::abort); - }); - connect(netJob.get(), &NetJob::progress, this, &JavaDownloader::progress); - connect(netJob.get(), &NetJob::failed, this, &JavaDownloader::emitFailed); - - connect(this, &Task::aborted, netJob.get(), &NetJob::abort); - - connect(netJob.get(), &NetJob::succeeded, [response, OS, isLegacy, this, netJob] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *response; - return; - } - auto versionArray = Json::ensureArray(Json::ensureObject(doc.object(), OS), isLegacy ? "jre-legacy" : "java-runtime-gamma"); - if (!versionArray.empty()) { - parseMojangManifest(isLegacy, versionArray); - - } else { - // mojang does not have a JRE for us, let's get azul zulu - downloadAzulMeta(OS, isLegacy, netJob.get()); - } - }); - - netJob->start(); -} -void JavaDownloader::parseMojangManifest(bool isLegacy, const QJsonArray& versionArray) -{ - setStatus(tr("Downloading Java from Mojang")); - auto url = Json::ensureString(Json::ensureObject(Json::ensureObject(versionArray[0]), "manifest"), "url"); - auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); - auto files = std::make_shared(); - - download->addNetAction(Net::Download::makeByteArray(QUrl(url), files)); - - connect(download.get(), &NetJob::finished, - [download, files, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); - connect(download.get(), &NetJob::progress, this, &JavaDownloader::progress); - connect(download.get(), &NetJob::failed, this, &JavaDownloader::emitFailed); - connect(this, &Task::aborted, download.get(), &NetJob::abort); - - connect(download.get(), &NetJob::succeeded, [files, isLegacy, this] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *files; - return; - } - downloadMojangJava(isLegacy, doc); - }); - download->start(); -} -void JavaDownloader::downloadMojangJava(bool isLegacy, const QJsonDocument& doc) -{ // valid json doc, begin making jre spot - auto output = FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java"), (isLegacy ? "java-legacy" : "java-current")); - FS::ensureFolderPathExists(output); - std::vector toDownload; - auto list = Json::ensureObject(Json::ensureObject(doc.object()), "files"); - for (const auto& paths : list.keys()) { - auto file = FS::PathCombine(output, paths); - - const QJsonObject& meta = Json::ensureObject(list, paths); - auto type = Json::ensureString(meta, "type"); - if (type == "directory") { - FS::ensureFolderPathExists(file); - } else if (type == "link") { - // this is linux only ! - auto path = Json::ensureString(meta, "target"); - if (!path.isEmpty()) { - auto target = FS::PathCombine(file, "../" + path); - QFile(target).link(file); - } - } else if (type == "file") { - // TODO download compressed version if it exists ? - auto raw = Json::ensureObject(Json::ensureObject(meta, "downloads"), "raw"); - auto isExec = Json::ensureBoolean(meta, "executable", false); - auto url = Json::ensureString(raw, "url"); - if (!url.isEmpty() && QUrl(url).isValid()) { - auto f = File{ file, url, QByteArray::fromHex(Json::ensureString(raw, "sha1").toLatin1()), isExec }; - toDownload.push_back(f); - } - } - } - auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network()); - for (const auto& file : toDownload) { - auto dl = Net::Download::makeFile(file.url, file.path); - if (!file.hash.isEmpty()) { - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, file.hash)); - } - if (file.isExec) { - connect(dl.get(), &Net::Download::succeeded, - [file] { QFile(file.path).setPermissions(QFile(file.path).permissions() | QFileDevice::Permissions(0x1111)); }); - } - elementDownload->addNetAction(dl); - } - connect(elementDownload, &NetJob::finished, [elementDownload, this] { - disconnect(this, &Task::aborted, elementDownload, &NetJob::abort); - elementDownload->deleteLater(); - }); - connect(elementDownload, &NetJob::progress, this, &JavaDownloader::progress); - connect(elementDownload, &NetJob::failed, this, &JavaDownloader::emitFailed); - - connect(this, &Task::aborted, elementDownload, &NetJob::abort); - connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); - elementDownload->start(); -} -void JavaDownloader::downloadAzulMeta(const QString& OS, bool isLegacy, const NetJob* netJob) -{ - setStatus(tr("Querying Azul meta")); - QString javaVersion = isLegacy ? QString("8.0") : QString("17.0"); - - QString azulOS; - QString arch; - QString bitness; - - mojangOStoAzul(OS, azulOS, arch, bitness); - auto metaResponse = std::make_shared(); - auto downloadJob = makeShared(QString("JRE::QueryAzulMeta"), APPLICATION->network()); - downloadJob->addNetAction( - Net::Download::makeByteArray(QString("https://api.azul.com/zulu/download/community/v1.0/bundles/?" - "java_version=%1" - "&os=%2" - "&arch=%3" - "&hw_bitness=%4" - "&ext=zip" // as a zip for all os, even linux NOTE !! Linux ARM is .deb or .tar.gz only !! - "&bundle_type=jre" // jre only - "&latest=true" // only get the one latest entry - ) - .arg(javaVersion, azulOS, arch, bitness), - metaResponse)); - connect(downloadJob.get(), &NetJob::finished, - [downloadJob, metaResponse, this] { disconnect(this, &Task::aborted, downloadJob.get(), &NetJob::abort); }); - connect(this, &Task::aborted, downloadJob.get(), &NetJob::abort); - connect(netJob, &NetJob::failed, this, &JavaDownloader::emitFailed); - connect(downloadJob.get(), &NetJob::progress, this, &JavaDownloader::progress); - connect(downloadJob.get(), &NetJob::succeeded, [metaResponse, isLegacy, this] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*metaResponse, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *metaResponse; - return; - } - auto array = Json::ensureArray(doc.array()); - if (!array.empty()) { - downloadAzulJava(isLegacy, array); - } else { - emitFailed(tr("No suitable JRE found")); - } - }); - downloadJob->start(); -} -void JavaDownloader::mojangOStoAzul(const QString& OS, QString& azulOS, QString& arch, QString& bitness) -{ - if (OS == "mac-os-arm64") { - // macos arm64 - azulOS = "macos"; - arch = "arm"; - bitness = "64"; - } else if (OS == "linux-arm64") { - // linux arm64 - azulOS = "linux"; - arch = "arm"; - bitness = "64"; - } else if (OS == "linux-arm") { - // linux arm (32) - azulOS = "linux"; - arch = "arm"; - bitness = "32"; - } else if (OS == "linux") { - // linux x86 64 (used for debugging, should never reach here) - azulOS = "linux"; - arch = "x86"; - bitness = "64"; - } -} -void JavaDownloader::downloadAzulJava(bool isLegacy, const QJsonArray& array) -{ // JRE found ! download the zip - setStatus(tr("Downloading Java from Azul")); - auto downloadURL = QUrl(array[0].toObject()["url"].toString()); - auto download = new NetJob(QString("JRE::DownloadJava"), APPLICATION->network()); - auto path = APPLICATION->instances()->getStagedInstancePath(); - auto temp = FS::PathCombine(path, "azulJRE.zip"); - - download->addNetAction(Net::Download::makeFile(downloadURL, temp)); - connect(download, &NetJob::finished, [download, this] { - disconnect(this, &Task::aborted, download, &NetJob::abort); - download->deleteLater(); - }); - connect(download, &NetJob::aborted, [path] { APPLICATION->instances()->destroyStagingPath(path); }); - connect(download, &NetJob::progress, this, &JavaDownloader::progress); - connect(download, &NetJob::failed, this, [this, path](QString reason) { - APPLICATION->instances()->destroyStagingPath(path); - emitFailed(std::move(reason)); - }); - connect(this, &Task::aborted, download, &NetJob::abort); - connect(download, &NetJob::succeeded, [isLegacy, temp, downloadURL, path, this] { - setStatus(tr("Extracting java")); - auto output = FS::PathCombine(QCoreApplication::applicationDirPath(), "java", isLegacy ? "java-legacy" : "java-current"); - // This should do all of the extracting and creating folders - MMCZip::extractDir(temp, downloadURL.fileName().chopped(4), output); - APPLICATION->instances()->destroyStagingPath(path); - emitSucceeded(); - }); - download->start(); -} -void JavaDownloader::showPrompts(QWidget* parent) -{ - QString sys = SysInfo::currentSystem(); - if (sys == "osx") { - sys = "mac-os"; - } - QString arch = SysInfo::useQTForArch(); - QString version; - if (sys == "windows") { - if (arch == "x86_64") { - version = "windows-x64"; - } else if (arch == "i386") { - version = "windows-x86"; - } else { - // Unknown, maybe arm, appending arch for downloader - version = "windows-" + arch; - } - } else if (sys == "mac-os") { - if (arch == "arm64") { - version = "mac-os-arm64"; - } else { - version = "mac-os"; - } - } else if (sys == "linux") { - if (arch == "x86_64") { - version = "linux"; - } else { - // will work for i386, and arm(64) - version = "linux-" + arch; - } - } else { - // ? ? ? ? ? unknown os, at least it won't have a java version on mojang or azul, display warning - QMessageBox::warning(parent, tr("Unknown OS"), - tr("The OS you are running is not supported by Mojang or Azul. Please install Java manually.")); - return; - } - // Selection using QMessageBox for java 8 or 17 - QMessageBox box( - QMessageBox::Icon::Question, tr("Java version"), - tr("Do you want to download Java version 8 or 17?\n Java 8 is recommended for older Minecraft versions, below 1.17\n Java 17 " - "is recommended for newer Minecraft versions, starting from 1.17"), - QMessageBox::NoButton, parent); - auto yes = box.addButton("Java 17", QMessageBox::AcceptRole); - auto no = box.addButton("Java 8", QMessageBox::AcceptRole); - auto both = box.addButton(tr("Download both"), QMessageBox::AcceptRole); - auto cancel = box.addButton(QMessageBox::Cancel); - - if (QFileInfo::exists(FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java"), "java-legacy"))) { - no->setEnabled(false); - } - if (QFileInfo::exists(FS::PathCombine(QCoreApplication::applicationDirPath(), QString("java"), "java-current"))) { - yes->setEnabled(false); - } - if (!yes->isEnabled() || !no->isEnabled()) { - both->setEnabled(false); - } - if (!yes->isEnabled() && !no->isEnabled()) { - QMessageBox::information(parent, tr("Already installed!"), tr("Both versions of Java are already installed!")); - return; - } - box.exec(); - if (box.clickedButton() == nullptr || box.clickedButton() == cancel) { - return; - } - bool isLegacy = box.clickedButton() == no; - - auto down = new JavaDownloader(isLegacy, version); - ProgressDialog dialog(parent); - dialog.setSkipButton(true, tr("Abort")); - bool finished_successfully = dialog.execWithTask(down); - // Run another download task for the other option as well! - if (finished_successfully && box.clickedButton() == both) { - auto dwn = new JavaDownloader(false, version); - ProgressDialog dg(parent); - dg.setSkipButton(true, tr("Abort")); - dg.execWithTask(dwn); - } -} diff --git a/launcher/JavaDownloader.h b/launcher/JavaDownloader.h deleted file mode 100644 index 54f058970..000000000 --- a/launcher/JavaDownloader.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include "net/NetJob.h" -#include "tasks/Task.h" - -class JavaDownloader : public Task { - Q_OBJECT - public: - /*Downloads the java to the runtimes folder*/ - explicit JavaDownloader(bool isLegacy, const QString& OS) : m_isLegacy(isLegacy), m_OS(OS) {} - - void executeTask() override; - [[nodiscard]] bool canAbort() const override { return true; } - static void showPrompts(QWidget* parent = nullptr); - - private: - bool m_isLegacy; - const QString& m_OS; - - void downloadMojangJavaList(const QString& OS, bool isLegacy); - void parseMojangManifest(bool isLegacy, const QJsonArray& versionArray); - void downloadMojangJava(bool isLegacy, const QJsonDocument& doc); - - static void mojangOStoAzul(const QString& OS, QString& azulOS, QString& arch, QString& bitness); - void downloadAzulMeta(const QString& OS, bool isLegacy, const NetJob* netJob); - void downloadAzulJava(bool isLegacy, const QJsonArray& array); -}; diff --git a/launcher/SysInfo.cpp b/launcher/SysInfo.cpp index f15dde0e4..0dfa74de7 100644 --- a/launcher/SysInfo.cpp +++ b/launcher/SysInfo.cpp @@ -17,13 +17,7 @@ bool rosettaDetect() if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) { return false; } - if (ret == 0) { - return false; - } - if (ret == 1) { - return true; - } - return false; + return ret == 1; } #endif @@ -47,7 +41,6 @@ QString currentSystem() QString useQTForArch() { - auto qtArch = QSysInfo::currentCpuArchitecture(); #if defined(Q_OS_MACOS) && !defined(Q_PROCESSOR_ARM) if (rosettaDetect()) { return "arm64"; @@ -55,7 +48,7 @@ QString useQTForArch() return "x86_64"; } #endif - return qtArch; + return QSysInfo::currentCpuArchitecture(); } int suitableMaxMem() @@ -71,4 +64,36 @@ int suitableMaxMem() return maxMemoryAlloc; } + +QString getSupportedJavaArchitecture() +{ + auto sys = currentSystem(); + auto arch = useQTForArch(); + if (sys == "windows") { + if (arch == "x86_64") + return "windows-x64"; + if (arch == "i386") + return "windows-x86"; + // Unknown, maybe arm, appending arch + return "windows-" + arch; + } + if (sys == "osx") { + if (arch == "arm64") + return "mac-os-arm64"; + if (arch.contains("64")) + return "mac-os-64"; + if (arch.contains("86")) + return "mac-os-86"; + // Unknown, maybe something new, appending arch + return "mac-os-" + arch; + } else if (sys == "linux") { + if (arch == "x86_64") + return "linux-x64"; + if (arch == "i386") + return "linux-x86"; + // will work for arm32 arm(64) + return "linux-" + arch; + } + return {}; +} } // namespace SysInfo diff --git a/launcher/SysInfo.h b/launcher/SysInfo.h index 499c3b1dd..f3688d60d 100644 --- a/launcher/SysInfo.h +++ b/launcher/SysInfo.h @@ -3,5 +3,6 @@ namespace SysInfo { QString currentSystem(); QString useQTForArch(); +QString getSupportedJavaArchitecture(); int suitableMaxMem(); } // namespace SysInfo diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 0ab9ae2c3..f1218f162 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -118,6 +118,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("Architecture"); case Path: return tr("Path"); + case Alias: + return tr("Alias"); case Time: return tr("Released"); } @@ -135,6 +137,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("CPU Architecture"); case Path: return tr("Filesystem path to this version"); + case Alias: + return tr("The alternative name of the java version"); case Time: return tr("Release date of this version"); } @@ -169,6 +173,8 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const return sourceModel()->data(parentIndex, BaseVersionList::ArchitectureRole); case Path: return sourceModel()->data(parentIndex, BaseVersionList::PathRole); + case Alias: + return sourceModel()->data(parentIndex, BaseVersionList::AliasRole); case Time: return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate(); default: @@ -314,6 +320,9 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw) if (roles.contains(BaseVersionList::PathRole)) { m_columns.push_back(Path); } + if (roles.contains(BaseVersionList::AliasRole)) { + m_columns.push_back(Alias); + } if (roles.contains(Meta::VersionList::TimeRole)) { m_columns.push_back(Time); } diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index 0863a7c80..2dc35a625 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -9,7 +9,7 @@ class VersionFilterModel; class VersionProxyModel : public QAbstractProxyModel { Q_OBJECT public: - enum Column { Name, ParentVersion, Branch, Type, Architecture, Path, Time }; + enum Column { Name, ParentVersion, Branch, Type, Architecture, Path, Time, Alias }; using FilterMap = QHash>; public: diff --git a/launcher/java/JavaRuntime.cpp b/launcher/java/JavaRuntime.cpp index 78651e991..be13f47e4 100644 --- a/launcher/java/JavaRuntime.cpp +++ b/launcher/java/JavaRuntime.cpp @@ -62,7 +62,7 @@ MetaPtr parseJavaMeta(const QJsonObject& in) } if (in.contains("version")) { - auto obj = Json::requireObject(in, "checksum"); + auto obj = Json::requireObject(in, "version"); auto name = Json::ensureString(obj, "name", ""); auto major = Json::ensureInteger(obj, "major", 0); auto minor = Json::ensureInteger(obj, "minor", 0); diff --git a/launcher/java/JavaVersion.cpp b/launcher/java/JavaVersion.cpp index 3de6f5ad6..f3ded9709 100644 --- a/launcher/java/JavaVersion.cpp +++ b/launcher/java/JavaVersion.cpp @@ -113,19 +113,20 @@ bool JavaVersion::operator>(const JavaVersion& rhs) JavaVersion::JavaVersion(int major, int minor, int security, int build, QString name) : m_major(major), m_minor(minor), m_security(security), m_name(name), m_parseable(true) { + QStringList versions; if (build != 0) { m_prerelease = QString::number(build); - m_string = m_prerelease; + versions.push_front(m_prerelease); } if (m_security != 0) - m_string = QString::number(m_security) + "." + m_string; - else if (!m_string.isEmpty()) { - m_string = "0." + m_string; - } + versions.push_front(QString::number(m_security)); + else if (!versions.isEmpty()) + versions.push_front("0"); + if (m_minor != 0) - m_string = QString::number(m_minor) + "." + m_string; - else if (!m_string.isEmpty()) { - m_string = "0." + m_string; - } - m_string = QString::number(m_major) + "." + m_string; + versions.push_front(QString::number(m_minor)); + else if (!versions.isEmpty()) + versions.push_front("0"); + versions.push_front(QString::number(m_major)); + m_string = versions.join("."); } diff --git a/launcher/java/download/ArchiveJavaDownloader.cpp b/launcher/java/download/ArchiveJavaDownloader.cpp index 5350fc4e6..bee65cf91 100644 --- a/launcher/java/download/ArchiveJavaDownloader.cpp +++ b/launcher/java/download/ArchiveJavaDownloader.cpp @@ -43,7 +43,7 @@ void ArchiveJavaDownloader::executeTask() if (m_checksum_type == "sha256") { hashType = QCryptographicHash::Algorithm::Sha256; } - action->addValidator(new Net::ChecksumValidator(hashType, m_checksum_hash.toLatin1())); + action->addValidator(new Net::ChecksumValidator(hashType, QByteArray::fromHex(m_checksum_hash.toUtf8()))); } download->addNetAction(action); auto fullPath = entry->getFullPath(); diff --git a/launcher/java/download/ManifestJavaDownloader.cpp b/launcher/java/download/ManifestJavaDownloader.cpp index 368d6431c..c0b7942a7 100644 --- a/launcher/java/download/ManifestJavaDownloader.cpp +++ b/launcher/java/download/ManifestJavaDownloader.cpp @@ -46,7 +46,7 @@ void ManifestJavaDownloader::executeTask() if (m_checksum_type == "sha256") { hashType = QCryptographicHash::Algorithm::Sha256; } - action->addValidator(new Net::ChecksumValidator(hashType, m_checksum_hash.toLatin1())); + action->addValidator(new Net::ChecksumValidator(hashType, QByteArray::fromHex(m_checksum_hash.toUtf8()))); } download->addNetAction(action); diff --git a/launcher/ui/java/JavaDownload.cpp b/launcher/ui/java/JavaDownload.cpp new file mode 100644 index 000000000..c03fb10e8 --- /dev/null +++ b/launcher/ui/java/JavaDownload.cpp @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2024 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "JavaDownload.h" +#include +#include +#include +#include +#include +#include "Application.h" +#include "BaseVersionList.h" +#include "FileSystem.h" +#include "QObjectPtr.h" +#include "SysInfo.h" +#include "java/JavaInstallList.h" +#include "java/download/ArchiveJavaDownloader.h" +#include "java/download/ManifestJavaDownloader.h" +#include "meta/Index.h" +#include "meta/Version.h" +#include "ui/dialogs/ProgressDialog.h" +#include "ui/java/ListModel.h" +#include "ui_JavaDownload.h" + +JavaDownload::JavaDownload(QWidget* parent) : QDialog(parent), ui(new Ui::JavaDownload) +{ + ui->setupUi(this); + ui->widget->initialize(new Java::JavaBaseVersionList("net.minecraft.java")); + ui->widget->selectCurrent(); + connect(ui->widget, &VersionSelectWidget::selectedVersionChanged, this, &JavaDownload::setSelectedVersion); + auto reset = ui->buttonBox->button(QDialogButtonBox::Reset); + connect(reset, &QPushButton::clicked, this, &JavaDownload::refresh); + connect(ui->widget_2, &VersionSelectWidget::selectedVersionChanged, this, &JavaDownload::setSelectedVersion2); +} + +JavaDownload::~JavaDownload() +{ + delete ui; +} + +void JavaDownload::setSelectedVersion(BaseVersion::Ptr version) +{ + if (!version) + return; + auto dcast = std::dynamic_pointer_cast(version); + if (!dcast) { + return; + } + ui->widget_2->initialize(new Java::InstallList(dcast, this)); + ui->widget_2->selectCurrent(); +} + +void JavaDownload::setSelectedVersion2(BaseVersion::Ptr version) +{ + if (!version) + return; + m_selectedVersion = std::dynamic_pointer_cast(ui->widget_2->selectedVersion()); +} +void JavaDownload::accept() +{ + if (!m_selectedVersion) { + m_selectedVersion = std::dynamic_pointer_cast(ui->widget_2->selectedVersion()); + qDebug() << "=========?" << (ui->widget_2->selectedVersion() != nullptr); + } + if (!m_selectedVersion) { + qDebug() << "faillllllllllllllllllllllllllll"; + return; + } + auto meta = m_selectedVersion->meta; + Task::Ptr task; + auto final_path = FS::PathCombine(APPLICATION->dataRoot(), "java", meta->name); + qDebug() << "===============>>=>>" << meta->checksumType << meta->checksumHash; + switch (meta->downloadType) { + case JavaRuntime::DownloadType::Manifest: + task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); + break; + case JavaRuntime::DownloadType::Archive: + task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); + break; + } + ProgressDialog pg(this); + pg.execWithTask(task.get()); + QDialog::accept(); +} + +void JavaDownload::refresh() +{ + ui->widget->loadList(); +} diff --git a/launcher/ui/java/JavaDownload.h b/launcher/ui/java/JavaDownload.h new file mode 100644 index 000000000..916d6b495 --- /dev/null +++ b/launcher/ui/java/JavaDownload.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2024 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include "BaseVersion.h" +#include "ui/java/ListModel.h" + +namespace Ui { +class JavaDownload; +} + +class JavaDownload : public QDialog { + Q_OBJECT + + public: + explicit JavaDownload(QWidget* parent = 0); + ~JavaDownload(); + + void accept(); + + public slots: + void refresh(); + + protected slots: + void setSelectedVersion(BaseVersion::Ptr version); + void setSelectedVersion2(BaseVersion::Ptr version); + + private: + Ui::JavaDownload* ui; + Java::JavaRuntimePtr m_selectedVersion; +}; diff --git a/launcher/ui/java/JavaDownload.ui b/launcher/ui/java/JavaDownload.ui new file mode 100644 index 000000000..bbc638e9b --- /dev/null +++ b/launcher/ui/java/JavaDownload.ui @@ -0,0 +1,100 @@ + + + JavaDownload + + + + 0 + 0 + 821 + 593 + + + + Dialog + + + + + + + + Major + + + + + + + + + + + + Runtime + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Retry + + + + + + + + VersionSelectWidget + QWidget +
ui/widgets/VersionSelectWidget.h
+ 1 +
+
+ + + + buttonBox + accepted() + JavaDownload + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + JavaDownload + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/launcher/ui/java/ListModel.cpp b/launcher/ui/java/ListModel.cpp new file mode 100644 index 000000000..71f8765eb --- /dev/null +++ b/launcher/ui/java/ListModel.cpp @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2024 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ListModel.h" +#include +#include +#include "BaseVersionList.h" +#include "StringUtils.h" +#include "SysInfo.h" + +namespace Java { + +InstallList::InstallList(Meta::Version::Ptr version, QObject* parent) : BaseVersionList(parent), m_version(version) +{ + if (version->isLoaded()) + sortVersions(); +} + +Task::Ptr InstallList::getLoadTask() +{ + m_version->load(Net::Mode::Online); + auto task = m_version->getCurrentTask(); + connect(task.get(), &Task::finished, this, &InstallList::sortVersions); + return task; +} + +const BaseVersion::Ptr InstallList::at(int i) const +{ + return m_vlist.at(i); +} + +bool InstallList::isLoaded() +{ + return m_version->isLoaded(); +} + +int InstallList::count() const +{ + return m_vlist.count(); +} + +QVariant InstallList::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() > count()) + return QVariant(); + + auto version = (m_vlist[index.row()]); + switch (role) { + case SortRole: + return -index.row(); + case VersionPointerRole: + return QVariant::fromValue(std::dynamic_pointer_cast(m_vlist[index.row()])); + case VersionIdRole: + return version->descriptor(); + case VersionRole: + return version->meta->version.toString(); + case RecommendedRole: + return version->meta->recommended; + case AliasRole: + return version->meta->name; + case ArchitectureRole: + return version->meta->vendor; + default: + return QVariant(); + } +} + +BaseVersionList::RoleList InstallList::providesRoles() const +{ + return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, AliasRole, ArchitectureRole }; +} + +bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right) +{ + auto rleft = std::dynamic_pointer_cast(right); + auto rright = std::dynamic_pointer_cast(left); + return (*rleft) > (*rright); +} + +void InstallList::sortVersions() +{ + QString versionStr = SysInfo::getSupportedJavaArchitecture(); + beginResetModel(); + auto runtimes = m_version->data()->runtimes; + if (versionStr.isEmpty() || !runtimes.contains(versionStr)) { + return; + } + auto javaruntimes = runtimes.value(versionStr); + for (auto v : javaruntimes) { + m_vlist.append(std::make_shared(v)); + } + std::sort(m_vlist.begin(), m_vlist.end(), sortJavas); + endResetModel(); +} + +bool JavaRuntime2::operator<(const JavaRuntime2& rhs) +{ + auto id = meta->version; + if (id < rhs.meta->version) { + return true; + } + if (id > rhs.meta->version) { + return false; + } + return StringUtils::naturalCompare(meta->name, rhs.meta->name, Qt::CaseInsensitive) < 0; +} + +bool JavaRuntime2::operator==(const JavaRuntime2& rhs) +{ + return meta->version == rhs.meta->version && meta->name == rhs.meta->name; +} + +bool JavaRuntime2::operator>(const JavaRuntime2& rhs) +{ + return (!operator<(rhs)) && (!operator==(rhs)); +} + +bool JavaRuntime2::operator<(BaseVersion& a) +{ + try { + return operator<(dynamic_cast(a)); + } catch (const std::bad_cast& e) { + return BaseVersion::operator<(a); + } +} + +bool JavaRuntime2::operator>(BaseVersion& a) +{ + try { + return operator>(dynamic_cast(a)); + } catch (const std::bad_cast& e) { + return BaseVersion::operator>(a); + } +} + +} // namespace Java diff --git a/launcher/ui/java/ListModel.h b/launcher/ui/java/ListModel.h new file mode 100644 index 000000000..3685d611d --- /dev/null +++ b/launcher/ui/java/ListModel.h @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2024 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include "java/JavaRuntime.h" +#include "meta/VersionList.h" + +namespace Java { + +class JavaBaseVersionList : public Meta::VersionList { + Q_OBJECT + public: + explicit JavaBaseVersionList(const QString& uid, QObject* parent = nullptr) : VersionList(uid, parent) {} + BaseVersionList::RoleList providesRoles() const { return { VersionRole, RecommendedRole, VersionPointerRole }; } +}; + +struct JavaRuntime2 : public BaseVersion { + JavaRuntime2() {} + JavaRuntime2(JavaRuntime::MetaPtr m) : meta(m) {} + virtual QString descriptor() override { return meta->version.toString(); } + + virtual QString name() override { return meta->name; } + + virtual QString typeString() const override { return meta->vendor; } + + virtual bool operator<(BaseVersion& a) override; + virtual bool operator>(BaseVersion& a) override; + bool operator<(const JavaRuntime2& rhs); + bool operator==(const JavaRuntime2& rhs); + bool operator>(const JavaRuntime2& rhs); + + JavaRuntime::MetaPtr meta; +}; + +using JavaRuntimePtr = std::shared_ptr; + +class InstallList : public BaseVersionList { + Q_OBJECT + + public: + explicit InstallList(Meta::Version::Ptr m_version, QObject* parent = 0); + + Task::Ptr getLoadTask() override; + bool isLoaded() override; + const BaseVersion::Ptr at(int i) const override; + int count() const override; + void sortVersions() override; + + QVariant data(const QModelIndex& index, int role) const override; + RoleList providesRoles() const override; + + protected slots: + void updateListData(QList) override {} + + protected: + Meta::Version::Ptr m_version; + QList m_vlist; +}; + +} // namespace Java +// class FilterModel : public QSortFilterProxyModel { +// Q_OBJECT +// public: +// FilterModel(QObject* parent = Q_NULLPTR); +// enum Sorting { ByName, ByGameVersion }; +// const QMap getAvailableSortings(); +// QString translateCurrentSorting(); +// void setSorting(Sorting sorting); +// Sorting getCurrentSorting(); +// void setSearchTerm(QString term); + +// protected: +// bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; +// bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; + +// private: +// QMap sortings; +// Sorting currentSorting; +// QString searchTerm; +// }; + +// class ListModel : public QAbstractListModel { +// Q_OBJECT +// private: +// ModpackList modpacks; +// QStringList m_failedLogos; +// QStringList m_loadingLogos; +// FTBLogoMap m_logoMap; +// QMap waitingCallbacks; + +// void requestLogo(QString file); +// QString translatePackType(PackType type) const; + +// private slots: +// void logoFailed(QString logo); +// void logoLoaded(QString logo, QIcon out); + +// public: +// ListModel(QObject* parent); +// ~ListModel(); +// int rowCount(const QModelIndex& parent) const override; +// int columnCount(const QModelIndex& parent) const override; +// QVariant data(const QModelIndex& index, int role) const override; +// Qt::ItemFlags flags(const QModelIndex& index) const override; + +// void fill(ModpackList modpacks); +// void addPack(Modpack modpack); +// void clear(); +// void remove(int row); + +// Modpack at(int row); +// void getLogo(const QString& logo, LogoCallback callback); +// }; diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 0f05b6c8f..09c951a3c 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -36,6 +36,7 @@ #include "JavaPage.h" #include "JavaCommon.h" +#include "ui/java/JavaDownload.h" #include "ui_JavaPage.h" #include @@ -51,7 +52,6 @@ #include #include #include "Application.h" -#include "JavaDownloader.h" #include "settings/SettingsObject.h" JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) @@ -169,7 +169,8 @@ void JavaPage::on_javaTestBtn_clicked() void JavaPage::on_javaDownloadBtn_clicked() { - JavaDownloader::showPrompts(this); + auto jdialog = new JavaDownload(this); + jdialog->exec(); } void JavaPage::on_maxMemSpinBox_valueChanged([[maybe_unused]] int i) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index a386a3bfe..df380bfb3 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -36,6 +36,7 @@ */ #include "InstanceSettingsPage.h" +#include "ui/java/JavaDownload.h" #include "ui_InstanceSettingsPage.h" #include @@ -53,7 +54,6 @@ #include "minecraft/auth/AccountList.h" #include "FileSystem.h" -#include "JavaDownloader.h" #include "java/JavaInstallList.h" #include "java/JavaUtils.h" @@ -387,7 +387,8 @@ void InstanceSettingsPage::loadSettings() void InstanceSettingsPage::on_javaDownloadBtn_clicked() { - JavaDownloader::showPrompts(this); + auto jdialog = new JavaDownload(this); + jdialog->exec(); } void InstanceSettingsPage::on_javaDetectBtn_clicked() diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 909ad7a01..7405ad114 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -13,13 +13,13 @@ #include "FileSystem.h" #include "JavaCommon.h" -#include "JavaDownloader.h" #include "java/JavaChecker.h" #include "java/JavaInstall.h" #include "java/JavaInstallList.h" #include "java/JavaUtils.h" #include "ui/dialogs/CustomMessageBox.h" +#include "ui/java/JavaDownload.h" #include "ui/widgets/VersionSelectWidget.h" #include "Application.h" @@ -274,7 +274,8 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked() } void JavaSettingsWidget::on_javaDownloadBtn_clicked() { - JavaDownloader::showPrompts(this); + auto jdialog = new JavaDownload(this); + jdialog->exec(); } void JavaSettingsWidget::on_javaStatusBtn_clicked() { From 5afe75e821516dbbde60d1b2d3a627a0d243b1fe Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 30 Jan 2024 12:37:34 +0200 Subject: [PATCH 029/120] Fixed some codeql warnings Signed-off-by: Trial97 --- launcher/JavaCommon.cpp | 4 ++-- launcher/JavaCommon.h | 4 ++-- launcher/java/JavaChecker.h | 2 +- launcher/java/JavaInstallList.cpp | 4 ++-- launcher/java/JavaVersion.cpp | 4 ++-- launcher/java/JavaVersion.h | 4 ++-- launcher/java/download/ArchiveJavaDownloader.cpp | 1 - launcher/launch/steps/CheckJava.cpp | 2 +- launcher/launch/steps/CheckJava.h | 2 +- launcher/ui/widgets/JavaSettingsWidget.cpp | 2 +- launcher/ui/widgets/JavaSettingsWidget.h | 2 +- 11 files changed, 15 insertions(+), 16 deletions(-) diff --git a/launcher/JavaCommon.cpp b/launcher/JavaCommon.cpp index cfc3cfe42..3cbf9f9d5 100644 --- a/launcher/JavaCommon.cpp +++ b/launcher/JavaCommon.cpp @@ -121,7 +121,7 @@ void JavaCommon::TestCheck::run() checker->start(); } -void JavaCommon::TestCheck::checkFinished(JavaChecker::Result result) +void JavaCommon::TestCheck::checkFinished(const JavaChecker::Result& result) { if (result.validity != JavaChecker::Result::Validity::Valid) { javaBinaryWasBad(m_parent, result); @@ -133,7 +133,7 @@ void JavaCommon::TestCheck::checkFinished(JavaChecker::Result result) checker->start(); } -void JavaCommon::TestCheck::checkFinishedWithArgs(JavaChecker::Result result) +void JavaCommon::TestCheck::checkFinishedWithArgs(const JavaChecker::Result& result) { if (result.validity == JavaChecker::Result::Validity::Valid) { javaWasOk(m_parent, result); diff --git a/launcher/JavaCommon.h b/launcher/JavaCommon.h index 7c5510efc..ca208b593 100644 --- a/launcher/JavaCommon.h +++ b/launcher/JavaCommon.h @@ -32,8 +32,8 @@ class TestCheck : public QObject { void finished(); private slots: - void checkFinished(JavaChecker::Result result); - void checkFinishedWithArgs(JavaChecker::Result result); + void checkFinished(const JavaChecker::Result& result); + void checkFinishedWithArgs(const JavaChecker::Result& result); private: JavaChecker::Ptr checker; diff --git a/launcher/java/JavaChecker.h b/launcher/java/JavaChecker.h index 0c6191c21..171a18b76 100644 --- a/launcher/java/JavaChecker.h +++ b/launcher/java/JavaChecker.h @@ -29,7 +29,7 @@ class JavaChecker : public Task { explicit JavaChecker(QString path, QString args, int minMem = 0, int maxMem = 0, int permGen = 0, int id = 0, QObject* parent = 0); signals: - void checkFinished(Result result); + void checkFinished(const Result& result); protected: virtual void executeTask() override; diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index ef99d6853..c14056964 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -170,7 +170,7 @@ void JavaListLoadTask::executeTask() int id = 0; for (QString candidate : candidate_paths) { auto checker = new JavaChecker(candidate, "", 0, 0, 0, id, this); - connect(checker, &JavaChecker::checkFinished, [this](JavaChecker::Result result) { m_results << result; }); + connect(checker, &JavaChecker::checkFinished, [this](const JavaChecker::Result& result) { m_results << result; }); job->addTask(Task::Ptr(checker)); id++; } @@ -181,7 +181,7 @@ void JavaListLoadTask::executeTask() void JavaListLoadTask::javaCheckerFinished() { QList candidates; - std::sort(m_results.begin(), m_results.end(), [](JavaChecker::Result a, JavaChecker::Result b) { return a.id < b.id; }); + std::sort(m_results.begin(), m_results.end(), [](const JavaChecker::Result& a, const JavaChecker::Result& b) { return a.id < b.id; }); qDebug() << "Found the following valid Java installations:"; for (auto result : m_results) { diff --git a/launcher/java/JavaVersion.cpp b/launcher/java/JavaVersion.cpp index f3ded9709..2dc23472e 100644 --- a/launcher/java/JavaVersion.cpp +++ b/launcher/java/JavaVersion.cpp @@ -43,12 +43,12 @@ QString JavaVersion::toString() const return m_string; } -bool JavaVersion::requiresPermGen() +bool JavaVersion::requiresPermGen() const { return !m_parseable || m_major < 8; } -bool JavaVersion::isModular() +bool JavaVersion::isModular() const { return m_parseable && m_major >= 9; } diff --git a/launcher/java/JavaVersion.h b/launcher/java/JavaVersion.h index eee992346..92c743bfb 100644 --- a/launcher/java/JavaVersion.h +++ b/launcher/java/JavaVersion.h @@ -24,9 +24,9 @@ class JavaVersion { bool operator==(const JavaVersion& rhs); bool operator>(const JavaVersion& rhs); - bool requiresPermGen(); + bool requiresPermGen() const; - bool isModular(); + bool isModular() const; QString toString() const; diff --git a/launcher/java/download/ArchiveJavaDownloader.cpp b/launcher/java/download/ArchiveJavaDownloader.cpp index bee65cf91..cb642357a 100644 --- a/launcher/java/download/ArchiveJavaDownloader.cpp +++ b/launcher/java/download/ArchiveJavaDownloader.cpp @@ -49,7 +49,6 @@ void ArchiveJavaDownloader::executeTask() auto fullPath = entry->getFullPath(); connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); - // connect(download.get(), &NetJob::aborted, [path] { APPLICATION->instances()->destroyStagingPath(path); }); connect(download.get(), &NetJob::progress, this, &ArchiveJavaDownloader::progress); connect(download.get(), &NetJob::failed, this, &ArchiveJavaDownloader::emitFailed); connect(this, &Task::aborted, download.get(), &NetJob::abort); diff --git a/launcher/launch/steps/CheckJava.cpp b/launcher/launch/steps/CheckJava.cpp index c776092fe..a8c7305ab 100644 --- a/launcher/launch/steps/CheckJava.cpp +++ b/launcher/launch/steps/CheckJava.cpp @@ -106,7 +106,7 @@ void CheckJava::executeTask() emitSucceeded(); } -void CheckJava::checkJavaFinished(JavaChecker::Result result) +void CheckJava::checkJavaFinished(const JavaChecker::Result& result) { switch (result.validity) { case JavaChecker::Result::Validity::Errored: { diff --git a/launcher/launch/steps/CheckJava.h b/launcher/launch/steps/CheckJava.h index 5ba9e4018..62b0c6bbb 100644 --- a/launcher/launch/steps/CheckJava.h +++ b/launcher/launch/steps/CheckJava.h @@ -28,7 +28,7 @@ class CheckJava : public LaunchStep { virtual void executeTask(); virtual bool canAbort() const { return false; } private slots: - void checkJavaFinished(JavaChecker::Result result); + void checkJavaFinished(const JavaChecker::Result& result); private: void printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString& vendor); diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 7405ad114..d6fbf00a3 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -377,7 +377,7 @@ void JavaSettingsWidget::checkJavaPath(const QString& path) m_checker->start(); } -void JavaSettingsWidget::checkFinished(JavaChecker::Result result) +void JavaSettingsWidget::checkFinished(const JavaChecker::Result& result) { m_result = result; switch (result.validity) { diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index d3cd2c5a7..b7db955a4 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -51,7 +51,7 @@ class JavaSettingsWidget : public QWidget { void on_javaBrowseBtn_clicked(); void on_javaStatusBtn_clicked(); void on_javaDownloadBtn_clicked(); - void checkFinished(JavaChecker::Result result); + void checkFinished(const JavaChecker::Result& result); protected: /* methods */ void checkJavaPathOnEdit(const QString& path); From 6c5bb3817bfe1a51924127f77965ea72506452aa Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 31 Jan 2024 18:07:28 +0200 Subject: [PATCH 030/120] Cleaned some code Signed-off-by: Trial97 --- launcher/java/JavaRuntime.cpp | 44 ++++++++++++++++- launcher/java/JavaRuntime.h | 18 ++++++- launcher/ui/java/JavaDownload.cpp | 35 +++++--------- launcher/ui/java/JavaDownload.h | 3 -- launcher/ui/java/ListModel.cpp | 69 ++++++--------------------- launcher/ui/java/ListModel.h | 78 +------------------------------ 6 files changed, 85 insertions(+), 162 deletions(-) diff --git a/launcher/java/JavaRuntime.cpp b/launcher/java/JavaRuntime.cpp index be13f47e4..e88955772 100644 --- a/launcher/java/JavaRuntime.cpp +++ b/launcher/java/JavaRuntime.cpp @@ -21,6 +21,7 @@ #include #include "Json.h" +#include "StringUtils.h" #include "java/JavaVersion.h" #include "minecraft/ParseUtils.h" @@ -47,7 +48,7 @@ MetaPtr parseJavaMeta(const QJsonObject& in) { auto meta = std::make_shared(); - meta->name = Json::ensureString(in, "name", ""); + meta->m_name = Json::ensureString(in, "name", ""); meta->vendor = Json::ensureString(in, "vendor", ""); meta->url = Json::ensureString(in, "url", ""); meta->releaseTime = timeFromS3Time(Json::ensureString(in, "releaseTime", "")); @@ -72,4 +73,45 @@ MetaPtr parseJavaMeta(const QJsonObject& in) } return meta; } + +bool Meta::operator<(const Meta& rhs) +{ + auto id = version; + if (id < rhs.version) { + return true; + } + if (id > rhs.version) { + return false; + } + return StringUtils::naturalCompare(m_name, rhs.m_name, Qt::CaseInsensitive) < 0; +} + +bool Meta::operator==(const Meta& rhs) +{ + return version == rhs.version && m_name == rhs.m_name; +} + +bool Meta::operator>(const Meta& rhs) +{ + return (!operator<(rhs)) && (!operator==(rhs)); +} + +bool Meta::operator<(BaseVersion& a) +{ + try { + return operator<(dynamic_cast(a)); + } catch (const std::bad_cast& e) { + return BaseVersion::operator<(a); + } +} + +bool Meta::operator>(BaseVersion& a) +{ + try { + return operator>(dynamic_cast(a)); + } catch (const std::bad_cast& e) { + return BaseVersion::operator>(a); + } +} + } // namespace JavaRuntime diff --git a/launcher/java/JavaRuntime.h b/launcher/java/JavaRuntime.h index 4c4efa288..654ba030a 100644 --- a/launcher/java/JavaRuntime.h +++ b/launcher/java/JavaRuntime.h @@ -23,14 +23,28 @@ #include +#include "BaseVersion.h" #include "java/JavaVersion.h" namespace JavaRuntime { enum class DownloadType { Manifest, Archive }; -struct Meta { - QString name; +class Meta : public BaseVersion { + public: + virtual QString descriptor() override { return version.toString(); } + + virtual QString name() override { return m_name; } + + virtual QString typeString() const override { return vendor; } + + virtual bool operator<(BaseVersion& a) override; + virtual bool operator>(BaseVersion& a) override; + bool operator<(const Meta& rhs); + bool operator==(const Meta& rhs); + bool operator>(const Meta& rhs); + + QString m_name; QString vendor; QString url; QDateTime releaseTime; diff --git a/launcher/ui/java/JavaDownload.cpp b/launcher/ui/java/JavaDownload.cpp index c03fb10e8..bae61a060 100644 --- a/launcher/ui/java/JavaDownload.cpp +++ b/launcher/ui/java/JavaDownload.cpp @@ -17,21 +17,23 @@ */ #include "JavaDownload.h" -#include -#include -#include -#include + +#include + #include + #include "Application.h" -#include "BaseVersionList.h" #include "FileSystem.h" #include "QObjectPtr.h" #include "SysInfo.h" -#include "java/JavaInstallList.h" + +#include "java/JavaRuntime.h" #include "java/download/ArchiveJavaDownloader.h" #include "java/download/ManifestJavaDownloader.h" + #include "meta/Index.h" #include "meta/Version.h" + #include "ui/dialogs/ProgressDialog.h" #include "ui/java/ListModel.h" #include "ui_JavaDownload.h" @@ -44,7 +46,6 @@ JavaDownload::JavaDownload(QWidget* parent) : QDialog(parent), ui(new Ui::JavaDo connect(ui->widget, &VersionSelectWidget::selectedVersionChanged, this, &JavaDownload::setSelectedVersion); auto reset = ui->buttonBox->button(QDialogButtonBox::Reset); connect(reset, &QPushButton::clicked, this, &JavaDownload::refresh); - connect(ui->widget_2, &VersionSelectWidget::selectedVersionChanged, this, &JavaDownload::setSelectedVersion2); } JavaDownload::~JavaDownload() @@ -54,8 +55,6 @@ JavaDownload::~JavaDownload() void JavaDownload::setSelectedVersion(BaseVersion::Ptr version) { - if (!version) - return; auto dcast = std::dynamic_pointer_cast(version); if (!dcast) { return; @@ -64,26 +63,14 @@ void JavaDownload::setSelectedVersion(BaseVersion::Ptr version) ui->widget_2->selectCurrent(); } -void JavaDownload::setSelectedVersion2(BaseVersion::Ptr version) -{ - if (!version) - return; - m_selectedVersion = std::dynamic_pointer_cast(ui->widget_2->selectedVersion()); -} void JavaDownload::accept() { - if (!m_selectedVersion) { - m_selectedVersion = std::dynamic_pointer_cast(ui->widget_2->selectedVersion()); - qDebug() << "=========?" << (ui->widget_2->selectedVersion() != nullptr); - } - if (!m_selectedVersion) { - qDebug() << "faillllllllllllllllllllllllllll"; + auto meta = std::dynamic_pointer_cast(ui->widget_2->selectedVersion()); + if (!meta) { return; } - auto meta = m_selectedVersion->meta; Task::Ptr task; - auto final_path = FS::PathCombine(APPLICATION->dataRoot(), "java", meta->name); - qDebug() << "===============>>=>>" << meta->checksumType << meta->checksumHash; + auto final_path = FS::PathCombine(APPLICATION->dataRoot(), "java", meta->m_name); switch (meta->downloadType) { case JavaRuntime::DownloadType::Manifest: task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); diff --git a/launcher/ui/java/JavaDownload.h b/launcher/ui/java/JavaDownload.h index 916d6b495..de0916ae5 100644 --- a/launcher/ui/java/JavaDownload.h +++ b/launcher/ui/java/JavaDownload.h @@ -20,7 +20,6 @@ #include #include "BaseVersion.h" -#include "ui/java/ListModel.h" namespace Ui { class JavaDownload; @@ -40,9 +39,7 @@ class JavaDownload : public QDialog { protected slots: void setSelectedVersion(BaseVersion::Ptr version); - void setSelectedVersion2(BaseVersion::Ptr version); private: Ui::JavaDownload* ui; - Java::JavaRuntimePtr m_selectedVersion; }; diff --git a/launcher/ui/java/ListModel.cpp b/launcher/ui/java/ListModel.cpp index 71f8765eb..11cd01130 100644 --- a/launcher/ui/java/ListModel.cpp +++ b/launcher/ui/java/ListModel.cpp @@ -17,11 +17,12 @@ */ #include "ListModel.h" -#include + #include + #include "BaseVersionList.h" -#include "StringUtils.h" #include "SysInfo.h" +#include "java/JavaRuntime.h" namespace Java { @@ -71,13 +72,13 @@ QVariant InstallList::data(const QModelIndex& index, int role) const case VersionIdRole: return version->descriptor(); case VersionRole: - return version->meta->version.toString(); + return version->version.toString(); case RecommendedRole: - return version->meta->recommended; + return version->recommended; case AliasRole: - return version->meta->name; + return version->name(); case ArchitectureRole: - return version->meta->vendor; + return version->vendor; default: return QVariant(); } @@ -90,8 +91,8 @@ BaseVersionList::RoleList InstallList::providesRoles() const bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right) { - auto rleft = std::dynamic_pointer_cast(right); - auto rright = std::dynamic_pointer_cast(left); + auto rleft = std::dynamic_pointer_cast(right); + auto rright = std::dynamic_pointer_cast(left); return (*rleft) > (*rright); } @@ -100,55 +101,13 @@ void InstallList::sortVersions() QString versionStr = SysInfo::getSupportedJavaArchitecture(); beginResetModel(); auto runtimes = m_version->data()->runtimes; - if (versionStr.isEmpty() || !runtimes.contains(versionStr)) { - return; + if (!versionStr.isEmpty() && runtimes.contains(versionStr)) { + m_vlist = runtimes.value(versionStr); + std::sort(m_vlist.begin(), m_vlist.end(), sortJavas); + } else { + m_vlist = {}; } - auto javaruntimes = runtimes.value(versionStr); - for (auto v : javaruntimes) { - m_vlist.append(std::make_shared(v)); - } - std::sort(m_vlist.begin(), m_vlist.end(), sortJavas); endResetModel(); } -bool JavaRuntime2::operator<(const JavaRuntime2& rhs) -{ - auto id = meta->version; - if (id < rhs.meta->version) { - return true; - } - if (id > rhs.meta->version) { - return false; - } - return StringUtils::naturalCompare(meta->name, rhs.meta->name, Qt::CaseInsensitive) < 0; -} - -bool JavaRuntime2::operator==(const JavaRuntime2& rhs) -{ - return meta->version == rhs.meta->version && meta->name == rhs.meta->name; -} - -bool JavaRuntime2::operator>(const JavaRuntime2& rhs) -{ - return (!operator<(rhs)) && (!operator==(rhs)); -} - -bool JavaRuntime2::operator<(BaseVersion& a) -{ - try { - return operator<(dynamic_cast(a)); - } catch (const std::bad_cast& e) { - return BaseVersion::operator<(a); - } -} - -bool JavaRuntime2::operator>(BaseVersion& a) -{ - try { - return operator>(dynamic_cast(a)); - } catch (const std::bad_cast& e) { - return BaseVersion::operator>(a); - } -} - } // namespace Java diff --git a/launcher/ui/java/ListModel.h b/launcher/ui/java/ListModel.h index 3685d611d..a157e0e8d 100644 --- a/launcher/ui/java/ListModel.h +++ b/launcher/ui/java/ListModel.h @@ -18,9 +18,6 @@ #pragma once -#include -#include -#include #include "java/JavaRuntime.h" #include "meta/VersionList.h" @@ -33,26 +30,6 @@ class JavaBaseVersionList : public Meta::VersionList { BaseVersionList::RoleList providesRoles() const { return { VersionRole, RecommendedRole, VersionPointerRole }; } }; -struct JavaRuntime2 : public BaseVersion { - JavaRuntime2() {} - JavaRuntime2(JavaRuntime::MetaPtr m) : meta(m) {} - virtual QString descriptor() override { return meta->version.toString(); } - - virtual QString name() override { return meta->name; } - - virtual QString typeString() const override { return meta->vendor; } - - virtual bool operator<(BaseVersion& a) override; - virtual bool operator>(BaseVersion& a) override; - bool operator<(const JavaRuntime2& rhs); - bool operator==(const JavaRuntime2& rhs); - bool operator>(const JavaRuntime2& rhs); - - JavaRuntime::MetaPtr meta; -}; - -using JavaRuntimePtr = std::shared_ptr; - class InstallList : public BaseVersionList { Q_OBJECT @@ -73,60 +50,7 @@ class InstallList : public BaseVersionList { protected: Meta::Version::Ptr m_version; - QList m_vlist; + QList m_vlist; }; } // namespace Java -// class FilterModel : public QSortFilterProxyModel { -// Q_OBJECT -// public: -// FilterModel(QObject* parent = Q_NULLPTR); -// enum Sorting { ByName, ByGameVersion }; -// const QMap getAvailableSortings(); -// QString translateCurrentSorting(); -// void setSorting(Sorting sorting); -// Sorting getCurrentSorting(); -// void setSearchTerm(QString term); - -// protected: -// bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; -// bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; - -// private: -// QMap sortings; -// Sorting currentSorting; -// QString searchTerm; -// }; - -// class ListModel : public QAbstractListModel { -// Q_OBJECT -// private: -// ModpackList modpacks; -// QStringList m_failedLogos; -// QStringList m_loadingLogos; -// FTBLogoMap m_logoMap; -// QMap waitingCallbacks; - -// void requestLogo(QString file); -// QString translatePackType(PackType type) const; - -// private slots: -// void logoFailed(QString logo); -// void logoLoaded(QString logo, QIcon out); - -// public: -// ListModel(QObject* parent); -// ~ListModel(); -// int rowCount(const QModelIndex& parent) const override; -// int columnCount(const QModelIndex& parent) const override; -// QVariant data(const QModelIndex& index, int role) const override; -// Qt::ItemFlags flags(const QModelIndex& index) const override; - -// void fill(ModpackList modpacks); -// void addPack(Modpack modpack); -// void clear(); -// void remove(int row); - -// Modpack at(int row); -// void getLogo(const QString& logo, LogoCallback callback); -// }; From 3c58fb06776000808029e8cc4d5207bfd0f57321 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 2 Feb 2024 15:51:32 +0200 Subject: [PATCH 031/120] Moving files around Signed-off-by: Trial97 --- launcher/BaseVersionList.cpp | 4 +- launcher/BaseVersionList.h | 4 +- launcher/CMakeLists.txt | 22 ++-- launcher/VersionProxyModel.cpp | 26 ++--- launcher/VersionProxyModel.h | 2 +- launcher/java/JavaInstallList.cpp | 4 +- .../{JavaRuntime.cpp => JavaMetadata.cpp} | 24 ++-- .../java/{JavaRuntime.h => JavaMetadata.h} | 16 +-- ...Downloader.cpp => ArchiveDownloadTask.cpp} | 22 ++-- ...JavaDownloader.h => ArchiveDownloadTask.h} | 12 +- ...ownloader.cpp => ManifestDownloadTask.cpp} | 20 ++-- ...avaDownloader.h => ManifestDownloadTask.h} | 13 ++- launcher/meta/VersionList.cpp | 8 +- launcher/meta/VersionList.h | 5 + launcher/minecraft/OneSixVersionFormat.cpp | 6 +- launcher/minecraft/VersionFile.h | 4 +- launcher/ui/java/JavaDownload.cpp | 90 --------------- launcher/ui/java/JavaDownloader.cpp | 109 ++++++++++++++++++ .../java/{JavaDownload.h => JavaDownloader.h} | 13 ++- .../{JavaDownload.ui => JavaDownloader.ui} | 12 +- .../java/{ListModel.cpp => VersionList.cpp} | 32 ++--- .../ui/java/{ListModel.h => VersionList.h} | 18 +-- launcher/ui/pages/global/JavaPage.cpp | 4 +- .../pages/instance/InstanceSettingsPage.cpp | 4 +- launcher/ui/widgets/JavaSettingsWidget.cpp | 4 +- 25 files changed, 254 insertions(+), 224 deletions(-) rename launcher/java/{JavaRuntime.cpp => JavaMetadata.cpp} (86%) rename launcher/java/{JavaRuntime.h => JavaMetadata.h} (84%) rename launcher/java/download/{ArchiveJavaDownloader.cpp => ArchiveDownloadTask.cpp} (82%) rename launcher/java/download/{ArchiveJavaDownloader.h => ArchiveDownloadTask.h} (82%) rename launcher/java/download/{ManifestJavaDownloader.cpp => ManifestDownloadTask.cpp} (87%) rename launcher/java/download/{ManifestJavaDownloader.h => ManifestDownloadTask.h} (82%) delete mode 100644 launcher/ui/java/JavaDownload.cpp create mode 100644 launcher/ui/java/JavaDownloader.cpp rename launcher/ui/java/{JavaDownload.h => JavaDownloader.h} (84%) rename launcher/ui/java/{JavaDownload.ui => JavaDownloader.ui} (86%) rename launcher/ui/java/{ListModel.cpp => VersionList.cpp} (76%) rename launcher/ui/java/{ListModel.h => VersionList.h} (71%) diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp index 576c3a413..afee8388a 100644 --- a/launcher/BaseVersionList.cpp +++ b/launcher/BaseVersionList.cpp @@ -110,7 +110,7 @@ QHash BaseVersionList::roleNames() const roles.insert(TypeRole, "type"); roles.insert(BranchRole, "branch"); roles.insert(PathRole, "path"); - roles.insert(AliasRole, "alias"); - roles.insert(ArchitectureRole, "architecture"); + roles.insert(JavaNameRole, "javaName"); + roles.insert(CPUArchitectureRole, "architecture"); return roles; } diff --git a/launcher/BaseVersionList.h b/launcher/BaseVersionList.h index c59d70570..bc37e9e53 100644 --- a/launcher/BaseVersionList.h +++ b/launcher/BaseVersionList.h @@ -48,8 +48,8 @@ class BaseVersionList : public QAbstractListModel { TypeRole, BranchRole, PathRole, - AliasRole, - ArchitectureRole, + JavaNameRole, + CPUArchitectureRole, SortRole }; using RoleList = QList; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index d703b8263..c7945d1b8 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -431,17 +431,17 @@ set(JAVA_SOURCES java/JavaVersion.h java/JavaVersion.cpp - java/JavaRuntime.h - java/JavaRuntime.cpp - java/download/ArchiveJavaDownloader.cpp - java/download/ArchiveJavaDownloader.h - java/download/ManifestJavaDownloader.cpp - java/download/ManifestJavaDownloader.h + java/JavaMetadata.h + java/JavaMetadata.cpp + java/download/ArchiveDownloadTask.cpp + java/download/ArchiveDownloadTask.h + java/download/ManifestDownloadTask.cpp + java/download/ManifestDownloadTask.h - ui/java/JavaDownload.h - ui/java/JavaDownload.cpp - ui/java/ListModel.h - ui/java/ListModel.cpp + ui/java/JavaDownloader.h + ui/java/JavaDownloader.cpp + ui/java/VersionList.h + ui/java/VersionList.cpp ) set(TRANSLATIONS_SOURCES @@ -1192,7 +1192,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ScrollMessageBox.ui ui/dialogs/BlockedModsDialog.ui ui/dialogs/ChooseProviderDialog.ui - ui/java/JavaDownload.ui + ui/java/JavaDownloader.ui ) qt_wrap_ui(PRISM_UPDATE_UI diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index f1218f162..070e952a4 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -114,12 +114,12 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("Branch"); case Type: return tr("Type"); - case Architecture: + case CPUArchitecture: return tr("Architecture"); case Path: return tr("Path"); - case Alias: - return tr("Alias"); + case JavaName: + return tr("Java Name"); case Time: return tr("Released"); } @@ -133,11 +133,11 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("The version's branch"); case Type: return tr("The version's type"); - case Architecture: + case CPUArchitecture: return tr("CPU Architecture"); case Path: return tr("Filesystem path to this version"); - case Alias: + case JavaName: return tr("The alternative name of the java version"); case Time: return tr("Release date of this version"); @@ -169,12 +169,12 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const return sourceModel()->data(parentIndex, BaseVersionList::BranchRole); case Type: return sourceModel()->data(parentIndex, BaseVersionList::TypeRole); - case Architecture: - return sourceModel()->data(parentIndex, BaseVersionList::ArchitectureRole); + case CPUArchitecture: + return sourceModel()->data(parentIndex, BaseVersionList::CPUArchitectureRole); case Path: return sourceModel()->data(parentIndex, BaseVersionList::PathRole); - case Alias: - return sourceModel()->data(parentIndex, BaseVersionList::AliasRole); + case JavaName: + return sourceModel()->data(parentIndex, BaseVersionList::JavaNameRole); case Time: return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate(); default: @@ -314,14 +314,14 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw) m_columns.push_back(ParentVersion); } */ - if (roles.contains(BaseVersionList::ArchitectureRole)) { - m_columns.push_back(Architecture); + if (roles.contains(BaseVersionList::CPUArchitectureRole)) { + m_columns.push_back(CPUArchitecture); } if (roles.contains(BaseVersionList::PathRole)) { m_columns.push_back(Path); } - if (roles.contains(BaseVersionList::AliasRole)) { - m_columns.push_back(Alias); + if (roles.contains(BaseVersionList::JavaNameRole)) { + m_columns.push_back(JavaName); } if (roles.contains(Meta::VersionList::TimeRole)) { m_columns.push_back(Time); diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index 2dc35a625..cb55b7f14 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -9,7 +9,7 @@ class VersionFilterModel; class VersionProxyModel : public QAbstractProxyModel { Q_OBJECT public: - enum Column { Name, ParentVersion, Branch, Type, Architecture, Path, Time, Alias }; + enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName }; using FilterMap = QHash>; public: diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index c14056964..d99201f24 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -108,7 +108,7 @@ QVariant JavaInstallList::data(const QModelIndex& index, int role) const return version->recommended; case PathRole: return version->path; - case ArchitectureRole: + case CPUArchitectureRole: return version->arch; default: return QVariant(); @@ -117,7 +117,7 @@ QVariant JavaInstallList::data(const QModelIndex& index, int role) const BaseVersionList::RoleList JavaInstallList::providesRoles() const { - return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole }; + return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, CPUArchitectureRole }; } void JavaInstallList::updateListData(QList versions) diff --git a/launcher/java/JavaRuntime.cpp b/launcher/java/JavaMetadata.cpp similarity index 86% rename from launcher/java/JavaRuntime.cpp rename to launcher/java/JavaMetadata.cpp index e88955772..b261122dc 100644 --- a/launcher/java/JavaRuntime.cpp +++ b/launcher/java/JavaMetadata.cpp @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -#include "java/JavaRuntime.h" +#include "java/JavaMetadata.h" #include @@ -25,7 +25,7 @@ #include "java/JavaVersion.h" #include "minecraft/ParseUtils.h" -namespace JavaRuntime { +namespace Java { DownloadType parseDownloadType(QString javaDownload) { @@ -44,9 +44,9 @@ QString downloadTypeToString(DownloadType javaDownload) } return ""; } -MetaPtr parseJavaMeta(const QJsonObject& in) +MetadataPtr parseJavaMeta(const QJsonObject& in) { - auto meta = std::make_shared(); + auto meta = std::make_shared(); meta->m_name = Json::ensureString(in, "name", ""); meta->vendor = Json::ensureString(in, "vendor", ""); @@ -74,7 +74,7 @@ MetaPtr parseJavaMeta(const QJsonObject& in) return meta; } -bool Meta::operator<(const Meta& rhs) +bool Metadata::operator<(const Metadata& rhs) { auto id = version; if (id < rhs.version) { @@ -86,32 +86,32 @@ bool Meta::operator<(const Meta& rhs) return StringUtils::naturalCompare(m_name, rhs.m_name, Qt::CaseInsensitive) < 0; } -bool Meta::operator==(const Meta& rhs) +bool Metadata::operator==(const Metadata& rhs) { return version == rhs.version && m_name == rhs.m_name; } -bool Meta::operator>(const Meta& rhs) +bool Metadata::operator>(const Metadata& rhs) { return (!operator<(rhs)) && (!operator==(rhs)); } -bool Meta::operator<(BaseVersion& a) +bool Metadata::operator<(BaseVersion& a) { try { - return operator<(dynamic_cast(a)); + return operator<(dynamic_cast(a)); } catch (const std::bad_cast& e) { return BaseVersion::operator<(a); } } -bool Meta::operator>(BaseVersion& a) +bool Metadata::operator>(BaseVersion& a) { try { - return operator>(dynamic_cast(a)); + return operator>(dynamic_cast(a)); } catch (const std::bad_cast& e) { return BaseVersion::operator>(a); } } -} // namespace JavaRuntime +} // namespace Java diff --git a/launcher/java/JavaRuntime.h b/launcher/java/JavaMetadata.h similarity index 84% rename from launcher/java/JavaRuntime.h rename to launcher/java/JavaMetadata.h index 654ba030a..dd3ae865c 100644 --- a/launcher/java/JavaRuntime.h +++ b/launcher/java/JavaMetadata.h @@ -26,11 +26,11 @@ #include "BaseVersion.h" #include "java/JavaVersion.h" -namespace JavaRuntime { +namespace Java { enum class DownloadType { Manifest, Archive }; -class Meta : public BaseVersion { +class Metadata : public BaseVersion { public: virtual QString descriptor() override { return version.toString(); } @@ -40,9 +40,9 @@ class Meta : public BaseVersion { virtual bool operator<(BaseVersion& a) override; virtual bool operator>(BaseVersion& a) override; - bool operator<(const Meta& rhs); - bool operator==(const Meta& rhs); - bool operator>(const Meta& rhs); + bool operator<(const Metadata& rhs); + bool operator==(const Metadata& rhs); + bool operator>(const Metadata& rhs); QString m_name; QString vendor; @@ -55,10 +55,10 @@ class Meta : public BaseVersion { QString packageType; JavaVersion version; }; -using MetaPtr = std::shared_ptr; +using MetadataPtr = std::shared_ptr; DownloadType parseDownloadType(QString javaDownload); QString downloadTypeToString(DownloadType javaDownload); -MetaPtr parseJavaMeta(const QJsonObject& libObj); +MetadataPtr parseJavaMeta(const QJsonObject& libObj); -} // namespace JavaRuntime \ No newline at end of file +} // namespace Java \ No newline at end of file diff --git a/launcher/java/download/ArchiveJavaDownloader.cpp b/launcher/java/download/ArchiveDownloadTask.cpp similarity index 82% rename from launcher/java/download/ArchiveJavaDownloader.cpp rename to launcher/java/download/ArchiveDownloadTask.cpp index cb642357a..847f3f364 100644 --- a/launcher/java/download/ArchiveJavaDownloader.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "java/download/ArchiveJavaDownloader.h" +#include "java/download/ArchiveDownloadTask.h" #include #include #include "MMCZip.h" @@ -25,11 +25,12 @@ #include "net/NetJob.h" #include "tasks/Task.h" -ArchiveJavaDownloader::ArchiveJavaDownloader(QUrl url, QString final_path, QString checksumType, QString checksumHash) +namespace Java { +ArchiveDownloadTask::ArchiveDownloadTask(QUrl url, QString final_path, QString checksumType, QString checksumHash) : m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash) {} -void ArchiveJavaDownloader::executeTask() +void ArchiveDownloadTask::executeTask() { // JRE found ! download the zip setStatus(tr("Downloading Java")); @@ -49,8 +50,8 @@ void ArchiveJavaDownloader::executeTask() auto fullPath = entry->getFullPath(); connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); - connect(download.get(), &NetJob::progress, this, &ArchiveJavaDownloader::progress); - connect(download.get(), &NetJob::failed, this, &ArchiveJavaDownloader::emitFailed); + connect(download.get(), &NetJob::progress, this, &ArchiveDownloadTask::progress); + connect(download.get(), &NetJob::failed, this, &ArchiveDownloadTask::emitFailed); connect(this, &Task::aborted, download.get(), &NetJob::abort); connect(download.get(), &NetJob::succeeded, [this, fullPath] { // This should do all of the extracting and creating folders @@ -59,7 +60,7 @@ void ArchiveJavaDownloader::executeTask() download->start(); } -void ArchiveJavaDownloader::extractJava(QString input) +void ArchiveDownloadTask::extractJava(QString input) { setStatus(tr("Extracting java")); auto zip = std::make_shared(input); @@ -79,14 +80,14 @@ void ArchiveJavaDownloader::extractJava(QString input) connect(this, &Task::aborted, zipTask.get(), &Task::abort); connect(zipTask.get(), &Task::finished, [zipTask, this] { disconnect(this, &Task::aborted, zipTask.get(), &Task::abort); }); - connect(zipTask.get(), &Task::succeeded, this, &ArchiveJavaDownloader::emitSucceeded); - connect(zipTask.get(), &Task::aborted, this, &ArchiveJavaDownloader::emitAborted); + connect(zipTask.get(), &Task::succeeded, this, &ArchiveDownloadTask::emitSucceeded); + connect(zipTask.get(), &Task::aborted, this, &ArchiveDownloadTask::emitAborted); connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) { progressStep->state = TaskStepState::Failed; stepProgress(*progressStep); emitFailed(reason); }); - connect(zipTask.get(), &Task::stepProgress, this, &ArchiveJavaDownloader::propagateStepProgress); + connect(zipTask.get(), &Task::stepProgress, this, &ArchiveDownloadTask::propagateStepProgress); connect(zipTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { progressStep->update(current, total); @@ -97,4 +98,5 @@ void ArchiveJavaDownloader::extractJava(QString input) stepProgress(*progressStep); }); zipTask->start(); -} \ No newline at end of file +} +} // namespace Java \ No newline at end of file diff --git a/launcher/java/download/ArchiveJavaDownloader.h b/launcher/java/download/ArchiveDownloadTask.h similarity index 82% rename from launcher/java/download/ArchiveJavaDownloader.h rename to launcher/java/download/ArchiveDownloadTask.h index 230f62b4d..88c0223d5 100644 --- a/launcher/java/download/ArchiveJavaDownloader.h +++ b/launcher/java/download/ArchiveDownloadTask.h @@ -21,11 +21,12 @@ #include #include "tasks/Task.h" -class ArchiveJavaDownloader : public Task { +namespace Java { +class ArchiveDownloadTask : public Task { Q_OBJECT public: - ArchiveJavaDownloader(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = ""); - virtual ~ArchiveJavaDownloader() = default; + ArchiveDownloadTask(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = ""); + virtual ~ArchiveDownloadTask() = default; [[nodiscard]] bool canAbort() const override { return true; } void executeTask() override; @@ -38,6 +39,5 @@ class ArchiveJavaDownloader : public Task { QString m_final_path; QString m_checksum_type; QString m_checksum_hash; - - Task::Ptr m_current_task; -}; \ No newline at end of file +}; +} // namespace Java \ No newline at end of file diff --git a/launcher/java/download/ManifestJavaDownloader.cpp b/launcher/java/download/ManifestDownloadTask.cpp similarity index 87% rename from launcher/java/download/ManifestJavaDownloader.cpp rename to launcher/java/download/ManifestDownloadTask.cpp index c0b7942a7..1a3071530 100644 --- a/launcher/java/download/ManifestJavaDownloader.cpp +++ b/launcher/java/download/ManifestDownloadTask.cpp @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "java/download/ManifestJavaDownloader.h" +#include "java/download/ManifestDownloadTask.h" #include "Application.h" #include "FileSystem.h" @@ -30,11 +30,12 @@ struct File { bool isExec; }; -ManifestJavaDownloader::ManifestJavaDownloader(QUrl url, QString final_path, QString checksumType, QString checksumHash) +namespace Java { +ManifestDownloadTask::ManifestDownloadTask(QUrl url, QString final_path, QString checksumType, QString checksumHash) : m_url(url), m_final_path(final_path), m_checksum_type(checksumType), m_checksum_hash(checksumHash) {} -void ManifestJavaDownloader::executeTask() +void ManifestDownloadTask::executeTask() { setStatus(tr("Downloading Java")); auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); @@ -51,8 +52,8 @@ void ManifestJavaDownloader::executeTask() download->addNetAction(action); connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); - connect(download.get(), &NetJob::progress, this, &ManifestJavaDownloader::progress); - connect(download.get(), &NetJob::failed, this, &ManifestJavaDownloader::emitFailed); + connect(download.get(), &NetJob::progress, this, &ManifestDownloadTask::progress); + connect(download.get(), &NetJob::failed, this, &ManifestDownloadTask::emitFailed); connect(this, &Task::aborted, download.get(), &NetJob::abort); connect(download.get(), &NetJob::succeeded, [files, this] { @@ -69,7 +70,7 @@ void ManifestJavaDownloader::executeTask() download->start(); } -void ManifestJavaDownloader::downloadJava(const QJsonDocument& doc) +void ManifestDownloadTask::downloadJava(const QJsonDocument& doc) { // valid json doc, begin making jre spot FS::ensureFolderPathExists(m_final_path); @@ -116,10 +117,11 @@ void ManifestJavaDownloader::downloadJava(const QJsonDocument& doc) disconnect(this, &Task::aborted, elementDownload, &NetJob::abort); elementDownload->deleteLater(); }); - connect(elementDownload, &NetJob::progress, this, &ManifestJavaDownloader::progress); - connect(elementDownload, &NetJob::failed, this, &ManifestJavaDownloader::emitFailed); + connect(elementDownload, &NetJob::progress, this, &ManifestDownloadTask::progress); + connect(elementDownload, &NetJob::failed, this, &ManifestDownloadTask::emitFailed); connect(this, &Task::aborted, elementDownload, &NetJob::abort); connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); elementDownload->start(); -} \ No newline at end of file +} +} // namespace Java \ No newline at end of file diff --git a/launcher/java/download/ManifestJavaDownloader.h b/launcher/java/download/ManifestDownloadTask.h similarity index 82% rename from launcher/java/download/ManifestJavaDownloader.h rename to launcher/java/download/ManifestDownloadTask.h index d7114f4bd..dcfee4d4d 100644 --- a/launcher/java/download/ManifestJavaDownloader.h +++ b/launcher/java/download/ManifestDownloadTask.h @@ -21,11 +21,13 @@ #include #include "tasks/Task.h" -class ManifestJavaDownloader : public Task { +namespace Java { + +class ManifestDownloadTask : public Task { Q_OBJECT public: - ManifestJavaDownloader(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = ""); - virtual ~ManifestJavaDownloader() = default; + ManifestDownloadTask(QUrl url, QString final_path, QString checksumType = "", QString checksumHash = ""); + virtual ~ManifestDownloadTask() = default; [[nodiscard]] bool canAbort() const override { return true; } void executeTask() override; @@ -38,6 +40,5 @@ class ManifestJavaDownloader : public Task { QString m_final_path; QString m_checksum_type; QString m_checksum_hash; - - Task::Ptr m_current_task; -}; \ No newline at end of file +}; +} // namespace Java \ No newline at end of file diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index 7b7ae1fa3..76b914b6a 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -101,10 +101,14 @@ QVariant VersionList::data(const QModelIndex& index, int role) const BaseVersionList::RoleList VersionList::providesRoles() const { - return { VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole, TypeRole, UidRole, - TimeRole, RequiresRole, SortRole, RecommendedRole, LatestRole, VersionPtrRole }; + return m_provided_roles; } +void VersionList::setProvidedRoles(RoleList roles) +{ + m_provided_roles = roles; +}; + QHash VersionList::roleNames() const { QHash roles = BaseVersionList::roleNames(); diff --git a/launcher/meta/VersionList.h b/launcher/meta/VersionList.h index 2c5624701..0890caf60 100644 --- a/launcher/meta/VersionList.h +++ b/launcher/meta/VersionList.h @@ -47,6 +47,8 @@ class VersionList : public BaseVersionList, public BaseEntity { RoleList providesRoles() const override; QHash roleNames() const override; + void setProvidedRoles(RoleList roles); + QString localFilename() const override; QString uid() const { return m_uid; } @@ -79,6 +81,9 @@ class VersionList : public BaseVersionList, public BaseEntity { Version::Ptr m_recommended; + RoleList m_provided_roles = { VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole, TypeRole, UidRole, + TimeRole, RequiresRole, SortRole, RecommendedRole, LatestRole, VersionPtrRole }; + void setupAddedVersion(int row, const Version::Ptr& version); }; } // namespace Meta diff --git a/launcher/minecraft/OneSixVersionFormat.cpp b/launcher/minecraft/OneSixVersionFormat.cpp index 5f3b4f2a2..56e9c8ca2 100644 --- a/launcher/minecraft/OneSixVersionFormat.cpp +++ b/launcher/minecraft/OneSixVersionFormat.cpp @@ -37,7 +37,7 @@ #include #include #include -#include "java/JavaRuntime.h" +#include "java/JavaMetadata.h" #include "minecraft/Agent.h" #include "minecraft/ParseUtils.h" @@ -261,9 +261,9 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument& doc auto runtimes = requireObject(root, "runtimes"); out->runtimes = {}; for (auto key : runtimes.keys()) { - QList list; + QList list; for (auto runtime : ensureArray(runtimes, key)) { - list.append(JavaRuntime::parseJavaMeta(ensureObject(runtime))); + list.append(Java::parseJavaMeta(ensureObject(runtime))); } out->runtimes[key] = list; } diff --git a/launcher/minecraft/VersionFile.h b/launcher/minecraft/VersionFile.h index 297c19709..a9c1473d2 100644 --- a/launcher/minecraft/VersionFile.h +++ b/launcher/minecraft/VersionFile.h @@ -47,7 +47,7 @@ #include "Agent.h" #include "Library.h" #include "ProblemProvider.h" -#include "java/JavaRuntime.h" +#include "java/JavaMetadata.h" #include "minecraft/Rule.h" class PackProfile; @@ -155,7 +155,7 @@ class VersionFile : public ProblemContainer { /// is volatile -- may be removed as soon as it is no longer needed by something else bool m_volatile = false; - QHash> runtimes; + QHash> runtimes; public: // Mojang: DEPRECATED list of 'downloads' - client jar, server jar, windows server exe, maybe more. diff --git a/launcher/ui/java/JavaDownload.cpp b/launcher/ui/java/JavaDownload.cpp deleted file mode 100644 index bae61a060..000000000 --- a/launcher/ui/java/JavaDownload.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2024 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "JavaDownload.h" - -#include - -#include - -#include "Application.h" -#include "FileSystem.h" -#include "QObjectPtr.h" -#include "SysInfo.h" - -#include "java/JavaRuntime.h" -#include "java/download/ArchiveJavaDownloader.h" -#include "java/download/ManifestJavaDownloader.h" - -#include "meta/Index.h" -#include "meta/Version.h" - -#include "ui/dialogs/ProgressDialog.h" -#include "ui/java/ListModel.h" -#include "ui_JavaDownload.h" - -JavaDownload::JavaDownload(QWidget* parent) : QDialog(parent), ui(new Ui::JavaDownload) -{ - ui->setupUi(this); - ui->widget->initialize(new Java::JavaBaseVersionList("net.minecraft.java")); - ui->widget->selectCurrent(); - connect(ui->widget, &VersionSelectWidget::selectedVersionChanged, this, &JavaDownload::setSelectedVersion); - auto reset = ui->buttonBox->button(QDialogButtonBox::Reset); - connect(reset, &QPushButton::clicked, this, &JavaDownload::refresh); -} - -JavaDownload::~JavaDownload() -{ - delete ui; -} - -void JavaDownload::setSelectedVersion(BaseVersion::Ptr version) -{ - auto dcast = std::dynamic_pointer_cast(version); - if (!dcast) { - return; - } - ui->widget_2->initialize(new Java::InstallList(dcast, this)); - ui->widget_2->selectCurrent(); -} - -void JavaDownload::accept() -{ - auto meta = std::dynamic_pointer_cast(ui->widget_2->selectedVersion()); - if (!meta) { - return; - } - Task::Ptr task; - auto final_path = FS::PathCombine(APPLICATION->dataRoot(), "java", meta->m_name); - switch (meta->downloadType) { - case JavaRuntime::DownloadType::Manifest: - task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); - break; - case JavaRuntime::DownloadType::Archive: - task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); - break; - } - ProgressDialog pg(this); - pg.execWithTask(task.get()); - QDialog::accept(); -} - -void JavaDownload::refresh() -{ - ui->widget->loadList(); -} diff --git a/launcher/ui/java/JavaDownloader.cpp b/launcher/ui/java/JavaDownloader.cpp new file mode 100644 index 000000000..9121988da --- /dev/null +++ b/launcher/ui/java/JavaDownloader.cpp @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2024 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "JavaDownloader.h" + +#include + +#include + +#include "Application.h" +#include "BaseVersionList.h" +#include "FileSystem.h" +#include "QObjectPtr.h" +#include "SysInfo.h" + +#include "java/JavaMetadata.h" +#include "java/download/ArchiveDownloadTask.h" +#include "java/download/ManifestDownloadTask.h" + +#include "meta/Index.h" +#include "meta/Version.h" + +#include "meta/VersionList.h" +#include "ui/dialogs/ProgressDialog.h" +#include "ui/java/VersionList.h" +#include "ui_JavaDownloader.h" + +namespace Java { + +Downloader::Downloader(QWidget* parent) : QDialog(parent), ui(new Ui::JavaDownloader) +{ + ui->setupUi(this); + auto versionList = new Meta::VersionList("net.minecraft.java", this); + versionList->setProvidedRoles({ BaseVersionList::VersionRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole }); + ui->majorVersionSelect->initialize(versionList); + ui->majorVersionSelect->selectCurrent(); + ui->majorVersionSelect->setEmptyString(tr("No java versions are currently available in the meta")); + ui->majorVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); + + ui->javaVersionSelect->setEmptyString(tr("No java versions are currently available for your OS.")); + ui->javaVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); + + ui->buttonBox->button(QDialogButtonBox::Retry)->setText(tr("Refresh")); + ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Download")); + + connect(ui->majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &Downloader::setSelectedVersion); + auto reset = ui->buttonBox->button(QDialogButtonBox::Reset); + connect(reset, &QPushButton::clicked, this, &Downloader::refresh); +} + +Downloader::~Downloader() +{ + delete ui; +} + +void Downloader::setSelectedVersion(BaseVersion::Ptr version) +{ + auto dcast = std::dynamic_pointer_cast(version); + if (!dcast) { + return; + } + ui->javaVersionSelect->initialize(new Java::VersionList(dcast, this)); + ui->javaVersionSelect->selectCurrent(); +} + +void Downloader::accept() +{ + auto meta = std::dynamic_pointer_cast(ui->javaVersionSelect->selectedVersion()); + if (!meta) { + return; + } + Task::Ptr task; + auto final_path = FS::PathCombine(APPLICATION->dataRoot(), "java", meta->m_name); + switch (meta->downloadType) { + case Java::DownloadType::Manifest: + task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); + break; + case Java::DownloadType::Archive: + task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); + break; + } + auto deletePath = [final_path] { FS::deletePath(final_path); }; + connect(task.get(), &Task::failed, this, deletePath); + connect(task.get(), &Task::aborted, this, deletePath); + ProgressDialog pg(this); + pg.execWithTask(task.get()); + QDialog::accept(); +} + +void Downloader::refresh() +{ + ui->majorVersionSelect->loadList(); +} +} // namespace Java diff --git a/launcher/ui/java/JavaDownload.h b/launcher/ui/java/JavaDownloader.h similarity index 84% rename from launcher/ui/java/JavaDownload.h rename to launcher/ui/java/JavaDownloader.h index de0916ae5..b8bdde41a 100644 --- a/launcher/ui/java/JavaDownload.h +++ b/launcher/ui/java/JavaDownloader.h @@ -22,15 +22,17 @@ #include "BaseVersion.h" namespace Ui { -class JavaDownload; +class JavaDownloader; } -class JavaDownload : public QDialog { +namespace Java { + +class Downloader : public QDialog { Q_OBJECT public: - explicit JavaDownload(QWidget* parent = 0); - ~JavaDownload(); + explicit Downloader(QWidget* parent = 0); + ~Downloader(); void accept(); @@ -41,5 +43,6 @@ class JavaDownload : public QDialog { void setSelectedVersion(BaseVersion::Ptr version); private: - Ui::JavaDownload* ui; + Ui::JavaDownloader* ui; }; +} // namespace Java diff --git a/launcher/ui/java/JavaDownload.ui b/launcher/ui/java/JavaDownloader.ui similarity index 86% rename from launcher/ui/java/JavaDownload.ui rename to launcher/ui/java/JavaDownloader.ui index bbc638e9b..0eeabb26d 100644 --- a/launcher/ui/java/JavaDownload.ui +++ b/launcher/ui/java/JavaDownloader.ui @@ -1,7 +1,7 @@ - JavaDownload - + JavaDownloader + 0 @@ -23,7 +23,7 @@ - + @@ -35,7 +35,7 @@
- +
@@ -67,7 +67,7 @@ buttonBox accepted() - JavaDownload + JavaDownloader accept() @@ -83,7 +83,7 @@ buttonBox rejected() - JavaDownload + JavaDownloader reject() diff --git a/launcher/ui/java/ListModel.cpp b/launcher/ui/java/VersionList.cpp similarity index 76% rename from launcher/ui/java/ListModel.cpp rename to launcher/ui/java/VersionList.cpp index 11cd01130..31353f2f7 100644 --- a/launcher/ui/java/ListModel.cpp +++ b/launcher/ui/java/VersionList.cpp @@ -16,46 +16,46 @@ * along with this program. If not, see . */ -#include "ListModel.h" +#include "VersionList.h" #include #include "BaseVersionList.h" #include "SysInfo.h" -#include "java/JavaRuntime.h" +#include "java/JavaMetadata.h" namespace Java { -InstallList::InstallList(Meta::Version::Ptr version, QObject* parent) : BaseVersionList(parent), m_version(version) +VersionList::VersionList(Meta::Version::Ptr version, QObject* parent) : BaseVersionList(parent), m_version(version) { if (version->isLoaded()) sortVersions(); } -Task::Ptr InstallList::getLoadTask() +Task::Ptr VersionList::getLoadTask() { m_version->load(Net::Mode::Online); auto task = m_version->getCurrentTask(); - connect(task.get(), &Task::finished, this, &InstallList::sortVersions); + connect(task.get(), &Task::finished, this, &VersionList::sortVersions); return task; } -const BaseVersion::Ptr InstallList::at(int i) const +const BaseVersion::Ptr VersionList::at(int i) const { return m_vlist.at(i); } -bool InstallList::isLoaded() +bool VersionList::isLoaded() { return m_version->isLoaded(); } -int InstallList::count() const +int VersionList::count() const { return m_vlist.count(); } -QVariant InstallList::data(const QModelIndex& index, int role) const +QVariant VersionList::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); @@ -75,28 +75,28 @@ QVariant InstallList::data(const QModelIndex& index, int role) const return version->version.toString(); case RecommendedRole: return version->recommended; - case AliasRole: + case JavaNameRole: return version->name(); - case ArchitectureRole: + case CPUArchitectureRole: return version->vendor; default: return QVariant(); } } -BaseVersionList::RoleList InstallList::providesRoles() const +BaseVersionList::RoleList VersionList::providesRoles() const { - return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, AliasRole, ArchitectureRole }; + return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, JavaNameRole, CPUArchitectureRole }; } bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right) { - auto rleft = std::dynamic_pointer_cast(right); - auto rright = std::dynamic_pointer_cast(left); + auto rleft = std::dynamic_pointer_cast(right); + auto rright = std::dynamic_pointer_cast(left); return (*rleft) > (*rright); } -void InstallList::sortVersions() +void VersionList::sortVersions() { QString versionStr = SysInfo::getSupportedJavaArchitecture(); beginResetModel(); diff --git a/launcher/ui/java/ListModel.h b/launcher/ui/java/VersionList.h similarity index 71% rename from launcher/ui/java/ListModel.h rename to launcher/ui/java/VersionList.h index a157e0e8d..d334ed564 100644 --- a/launcher/ui/java/ListModel.h +++ b/launcher/ui/java/VersionList.h @@ -18,23 +18,17 @@ #pragma once -#include "java/JavaRuntime.h" -#include "meta/VersionList.h" +#include "BaseVersionList.h" +#include "java/JavaMetadata.h" +#include "meta/Version.h" namespace Java { -class JavaBaseVersionList : public Meta::VersionList { - Q_OBJECT - public: - explicit JavaBaseVersionList(const QString& uid, QObject* parent = nullptr) : VersionList(uid, parent) {} - BaseVersionList::RoleList providesRoles() const { return { VersionRole, RecommendedRole, VersionPointerRole }; } -}; - -class InstallList : public BaseVersionList { +class VersionList : public BaseVersionList { Q_OBJECT public: - explicit InstallList(Meta::Version::Ptr m_version, QObject* parent = 0); + explicit VersionList(Meta::Version::Ptr m_version, QObject* parent = 0); Task::Ptr getLoadTask() override; bool isLoaded() override; @@ -50,7 +44,7 @@ class InstallList : public BaseVersionList { protected: Meta::Version::Ptr m_version; - QList m_vlist; + QList m_vlist; }; } // namespace Java diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 09c951a3c..9b21aad72 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -36,7 +36,7 @@ #include "JavaPage.h" #include "JavaCommon.h" -#include "ui/java/JavaDownload.h" +#include "ui/java/JavaDownloader.h" #include "ui_JavaPage.h" #include @@ -169,7 +169,7 @@ void JavaPage::on_javaTestBtn_clicked() void JavaPage::on_javaDownloadBtn_clicked() { - auto jdialog = new JavaDownload(this); + auto jdialog = new Java::Downloader(this); jdialog->exec(); } diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index df380bfb3..b962406d1 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -36,7 +36,7 @@ */ #include "InstanceSettingsPage.h" -#include "ui/java/JavaDownload.h" +#include "ui/java/JavaDownloader.h" #include "ui_InstanceSettingsPage.h" #include @@ -387,7 +387,7 @@ void InstanceSettingsPage::loadSettings() void InstanceSettingsPage::on_javaDownloadBtn_clicked() { - auto jdialog = new JavaDownload(this); + auto jdialog = new Java::Downloader(this); jdialog->exec(); } diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index d6fbf00a3..3f4fe08ea 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -19,7 +19,7 @@ #include "java/JavaUtils.h" #include "ui/dialogs/CustomMessageBox.h" -#include "ui/java/JavaDownload.h" +#include "ui/java/JavaDownloader.h" #include "ui/widgets/VersionSelectWidget.h" #include "Application.h" @@ -274,7 +274,7 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked() } void JavaSettingsWidget::on_javaDownloadBtn_clicked() { - auto jdialog = new JavaDownload(this); + auto jdialog = new Java::Downloader(this); jdialog->exec(); } void JavaSettingsWidget::on_javaStatusBtn_clicked() From 0384e652fb42ea18526a168a2370f8431cdcbc0f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 2 Feb 2024 22:42:42 +0200 Subject: [PATCH 032/120] Finished up the download dialog Signed-off-by: Trial97 --- launcher/BaseVersionList.cpp | 1 + launcher/BaseVersionList.h | 1 + launcher/VersionProxyModel.cpp | 9 +++++++++ launcher/VersionProxyModel.h | 2 +- launcher/ui/java/VersionList.cpp | 11 +++++++++-- 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp index afee8388a..1456a17bd 100644 --- a/launcher/BaseVersionList.cpp +++ b/launcher/BaseVersionList.cpp @@ -112,5 +112,6 @@ QHash BaseVersionList::roleNames() const roles.insert(PathRole, "path"); roles.insert(JavaNameRole, "javaName"); roles.insert(CPUArchitectureRole, "architecture"); + roles.insert(JavaVendorRole, "javaVendor"); return roles; } diff --git a/launcher/BaseVersionList.h b/launcher/BaseVersionList.h index bc37e9e53..7517c71b4 100644 --- a/launcher/BaseVersionList.h +++ b/launcher/BaseVersionList.h @@ -50,6 +50,7 @@ class BaseVersionList : public QAbstractListModel { PathRole, JavaNameRole, CPUArchitectureRole, + JavaVendorRole, SortRole }; using RoleList = QList; diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 070e952a4..ed4c0767d 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -116,6 +116,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("Type"); case CPUArchitecture: return tr("Architecture"); + case JavaVendor: + return tr("Vendor"); case Path: return tr("Path"); case JavaName: @@ -135,6 +137,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("The version's type"); case CPUArchitecture: return tr("CPU Architecture"); + case JavaVendor: + return tr("Java vendor"); case Path: return tr("Filesystem path to this version"); case JavaName: @@ -171,6 +175,8 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const return sourceModel()->data(parentIndex, BaseVersionList::TypeRole); case CPUArchitecture: return sourceModel()->data(parentIndex, BaseVersionList::CPUArchitectureRole); + case JavaVendor: + return sourceModel()->data(parentIndex, BaseVersionList::JavaVendorRole); case Path: return sourceModel()->data(parentIndex, BaseVersionList::PathRole); case JavaName: @@ -317,6 +323,9 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw) if (roles.contains(BaseVersionList::CPUArchitectureRole)) { m_columns.push_back(CPUArchitecture); } + if (roles.contains(BaseVersionList::JavaVendorRole)) { + m_columns.push_back(JavaVendor); + } if (roles.contains(BaseVersionList::PathRole)) { m_columns.push_back(Path); } diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index cb55b7f14..5a1017bee 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -9,7 +9,7 @@ class VersionFilterModel; class VersionProxyModel : public QAbstractProxyModel { Q_OBJECT public: - enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName }; + enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName, JavaVendor }; using FilterMap = QHash>; public: diff --git a/launcher/ui/java/VersionList.cpp b/launcher/ui/java/VersionList.cpp index 31353f2f7..7c5668d20 100644 --- a/launcher/ui/java/VersionList.cpp +++ b/launcher/ui/java/VersionList.cpp @@ -23,6 +23,7 @@ #include "BaseVersionList.h" #include "SysInfo.h" #include "java/JavaMetadata.h" +#include "meta/VersionList.h" namespace Java { @@ -77,8 +78,12 @@ QVariant VersionList::data(const QModelIndex& index, int role) const return version->recommended; case JavaNameRole: return version->name(); - case CPUArchitectureRole: + case JavaVendorRole: return version->vendor; + case TypeRole: + return version->packageType; + case Meta::VersionList::TimeRole: + return version->releaseTime; default: return QVariant(); } @@ -86,7 +91,8 @@ QVariant VersionList::data(const QModelIndex& index, int role) const BaseVersionList::RoleList VersionList::providesRoles() const { - return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, JavaNameRole, CPUArchitectureRole }; + return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, + JavaNameRole, JavaVendorRole, TypeRole, Meta::VersionList::TimeRole }; } bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right) @@ -106,6 +112,7 @@ void VersionList::sortVersions() std::sort(m_vlist.begin(), m_vlist.end(), sortJavas); } else { m_vlist = {}; + qWarning() << "Your operating system is not yet supported: " << SysInfo::currentSystem() << " " << SysInfo::useQTForArch(); } endResetModel(); } From 82b15268bc8566be4b320c24b41113f8f25c2204 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 3 Feb 2024 00:11:05 +0200 Subject: [PATCH 033/120] preparing java autodownload Signed-off-by: Trial97 --- launcher/java/JavaVersion.h | 10 +++++----- launcher/minecraft/LaunchProfile.cpp | 9 +++++++++ launcher/minecraft/LaunchProfile.h | 4 ++++ launcher/minecraft/VersionFile.cpp | 1 + launcher/ui/java/JavaDownloader.cpp | 6 +++--- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/launcher/java/JavaVersion.h b/launcher/java/JavaVersion.h index 92c743bfb..dfb4770da 100644 --- a/launcher/java/JavaVersion.h +++ b/launcher/java/JavaVersion.h @@ -30,11 +30,11 @@ class JavaVersion { QString toString() const; - int major() { return m_major; } - int minor() { return m_minor; } - int security() { return m_security; } - QString build() { return m_prerelease; } - QString name() { return m_name; } + int major() const { return m_major; } + int minor() const { return m_minor; } + int security() const { return m_security; } + QString build() const { return m_prerelease; } + QString name() const { return m_name; } private: QString m_string; diff --git a/launcher/minecraft/LaunchProfile.cpp b/launcher/minecraft/LaunchProfile.cpp index cf819b411..77072472c 100644 --- a/launcher/minecraft/LaunchProfile.cpp +++ b/launcher/minecraft/LaunchProfile.cpp @@ -164,6 +164,10 @@ void LaunchProfile::applyCompatibleJavaMajors(QList& javaMajor) { m_compatibleJavaMajors.append(javaMajor); } +void LaunchProfile::applyCompatibleJavaName(QString javaName) +{ + m_compatibleJavaName = javaName; +} void LaunchProfile::applyLibrary(LibraryPtr library, const RuntimeContext& runtimeContext) { @@ -334,6 +338,11 @@ const QList& LaunchProfile::getCompatibleJavaMajors() const return m_compatibleJavaMajors; } +const QString LaunchProfile::getCompatibleJavaName() const +{ + return m_compatibleJavaName; +} + void LaunchProfile::getLibraryFiles(const RuntimeContext& runtimeContext, QStringList& jars, QStringList& nativeJars, diff --git a/launcher/minecraft/LaunchProfile.h b/launcher/minecraft/LaunchProfile.h index 12b312383..f1be6fee0 100644 --- a/launcher/minecraft/LaunchProfile.h +++ b/launcher/minecraft/LaunchProfile.h @@ -59,6 +59,7 @@ class LaunchProfile : public ProblemProvider { void applyMavenFile(LibraryPtr library, const RuntimeContext& runtimeContext); void applyAgent(AgentPtr agent, const RuntimeContext& runtimeContext); void applyCompatibleJavaMajors(QList& javaMajor); + void applyCompatibleJavaName(QString javaName); void applyMainJar(LibraryPtr jar); void applyProblemSeverity(ProblemSeverity severity); /// clear the profile @@ -80,6 +81,7 @@ class LaunchProfile : public ProblemProvider { const QList& getMavenFiles() const; const QList& getAgents() const; const QList& getCompatibleJavaMajors() const; + const QString getCompatibleJavaName() const; const LibraryPtr getMainJar() const; void getLibraryFiles(const RuntimeContext& runtimeContext, QStringList& jars, @@ -150,5 +152,7 @@ class LaunchProfile : public ProblemProvider { /// compatible java major versions QList m_compatibleJavaMajors; + QString m_compatibleJavaName; + ProblemSeverity m_problemSeverity = ProblemSeverity::None; }; diff --git a/launcher/minecraft/VersionFile.cpp b/launcher/minecraft/VersionFile.cpp index 6632bb8bf..8ee61128f 100644 --- a/launcher/minecraft/VersionFile.cpp +++ b/launcher/minecraft/VersionFile.cpp @@ -73,6 +73,7 @@ void VersionFile::applyTo(LaunchProfile* profile, const RuntimeContext& runtimeC profile->applyMods(mods); profile->applyTraits(traits); profile->applyCompatibleJavaMajors(compatibleJavaMajors); + profile->applyCompatibleJavaName(compatibleJavaName); for (auto library : libraries) { profile->applyLibrary(library, runtimeContext); diff --git a/launcher/ui/java/JavaDownloader.cpp b/launcher/ui/java/JavaDownloader.cpp index 9121988da..3552f0ef5 100644 --- a/launcher/ui/java/JavaDownloader.cpp +++ b/launcher/ui/java/JavaDownloader.cpp @@ -45,9 +45,9 @@ namespace Java { Downloader::Downloader(QWidget* parent) : QDialog(parent), ui(new Ui::JavaDownloader) { ui->setupUi(this); - auto versionList = new Meta::VersionList("net.minecraft.java", this); + auto versionList = APPLICATION->metadataIndex()->get("net.minecraft.java"); versionList->setProvidedRoles({ BaseVersionList::VersionRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole }); - ui->majorVersionSelect->initialize(versionList); + ui->majorVersionSelect->initialize(versionList.get()); ui->majorVersionSelect->selectCurrent(); ui->majorVersionSelect->setEmptyString(tr("No java versions are currently available in the meta")); ui->majorVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); @@ -85,7 +85,7 @@ void Downloader::accept() return; } Task::Ptr task; - auto final_path = FS::PathCombine(APPLICATION->dataRoot(), "java", meta->m_name); + auto final_path = FS::PathCombine(APPLICATION->dataRoot(), "java", meta->vendor, meta->m_name); switch (meta->downloadType) { case Java::DownloadType::Manifest: task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); From ba990e075bc9bea8b03857a643005f6fe9301a34 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Feb 2024 19:45:46 +0200 Subject: [PATCH 034/120] Added JavaPath function Signed-off-by: Trial97 --- launcher/Application.cpp | 7 ++++--- launcher/Application.h | 3 +++ launcher/java/JavaUtils.cpp | 28 +++++++++++++++++++++++++++- launcher/java/JavaUtils.h | 1 + launcher/ui/java/JavaDownloader.cpp | 2 +- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 679de711e..20da46187 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -48,7 +48,6 @@ #include "net/PasteUpload.h" #include "pathmatcher/MultiMatcher.h" #include "pathmatcher/SimplePrefixMatcher.h" -#include "settings/INIFile.h" #include "ui/InstanceWindow.h" #include "ui/MainWindow.h" @@ -106,8 +105,6 @@ #include "icons/IconList.h" #include "net/HttpMetaCache.h" -#include "java/JavaUtils.h" - #include "updater/ExternalUpdater.h" #include "tools/JProfiler.h" @@ -1833,3 +1830,7 @@ QUrl Application::normalizeImportUrl(QString const& url) return QUrl::fromUserInput(url); } } +const QString Application::javaPath() +{ + return FS::PathCombine(m_dataPath, "java"); +} diff --git a/launcher/Application.h b/launcher/Application.h index 85bf2dff4..ba65edd82 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -162,6 +162,9 @@ class Application : public QApplication { /// the data path the application is using const QString& dataRoot() { return m_dataPath; } + /// the java installed path the application is using + const QString javaPath(); + bool isPortable() { return m_portable; } const Capabilities capabilities() { return m_capabilities; } diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 67f1fd3a7..ff5ba5efe 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -337,6 +337,7 @@ QList JavaUtils::FindJavaPaths() } candidates.append(getMinecraftJavaBundle()); + candidates.append(getPrismJavaBundle()); candidates = addJavasFromEnv(candidates); candidates.removeDuplicates(); return candidates; @@ -363,6 +364,7 @@ QList JavaUtils::FindJavaPaths() javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Commands/java"); } javas.append(getMinecraftJavaBundle()); + javas.append(getPrismJavaBundle()); javas = addJavasFromEnv(javas); javas.removeDuplicates(); return javas; @@ -393,7 +395,6 @@ QList JavaUtils::FindJavaPaths() scanJavaDir(snap + dirPath); } }; - scanJavaDir(FS::PathCombine(APPLICATION->dataRoot(), "java")); // oracle RPMs scanJavaDirs("/usr/java"); // general locations used by distro packaging @@ -416,6 +417,7 @@ QList JavaUtils::FindJavaPaths() scanJavaDirs(FS::PathCombine(home, ".sdkman/candidates/java")); javas.append(getMinecraftJavaBundle()); + javas.append(getPrismJavaBundle()); javas = addJavasFromEnv(javas); javas.removeDuplicates(); return javas; @@ -429,6 +431,8 @@ QList JavaUtils::FindJavaPaths() javas.append(this->GetDefaultJava()->path); javas.append(getMinecraftJavaBundle()); + javas.append(getPrismJavaBundle()); + javas.removeDuplicates(); return addJavasFromEnv(javas); } #endif @@ -484,3 +488,25 @@ QStringList getMinecraftJavaBundle() } return javas; } + +QStringList getPrismJavaBundle() +{ + QList javas; + QDir dir(APPLICATION->javaPath()); + if (!dir.exists()) + return javas; + + QString executable = "java"; +#if defined(Q_OS_WIN32) + executable += "w.exe"; +#endif + + auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (auto& entry : entries) { + QString prefix; + prefix = entry.canonicalFilePath(); + javas.append(FS::PathCombine(prefix, "jre", "bin", executable)); + javas.append(FS::PathCombine(prefix, "bin", executable)); + } + return javas; +} diff --git a/launcher/java/JavaUtils.h b/launcher/java/JavaUtils.h index 0beb8c67a..aa5315a19 100644 --- a/launcher/java/JavaUtils.h +++ b/launcher/java/JavaUtils.h @@ -26,6 +26,7 @@ QString stripVariableEntries(QString name, QString target, QString remove); QProcessEnvironment CleanEnviroment(); QStringList getMinecraftJavaBundle(); +QStringList getPrismJavaBundle(); class JavaUtils : public QObject { Q_OBJECT diff --git a/launcher/ui/java/JavaDownloader.cpp b/launcher/ui/java/JavaDownloader.cpp index 3552f0ef5..4495210c3 100644 --- a/launcher/ui/java/JavaDownloader.cpp +++ b/launcher/ui/java/JavaDownloader.cpp @@ -85,7 +85,7 @@ void Downloader::accept() return; } Task::Ptr task; - auto final_path = FS::PathCombine(APPLICATION->dataRoot(), "java", meta->vendor, meta->m_name); + auto final_path = FS::PathCombine(APPLICATION->javaPath(), meta->m_name); switch (meta->downloadType) { case Java::DownloadType::Manifest: task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); From 3d29da916ded28e320eda2654ba42f529e682019 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Feb 2024 20:15:19 +0200 Subject: [PATCH 035/120] Made Java path configurable Signed-off-by: Trial97 --- launcher/Application.cpp | 3 +- launcher/ui/pages/global/LauncherPage.cpp | 12 +++ launcher/ui/pages/global/LauncherPage.h | 1 + launcher/ui/pages/global/LauncherPage.ui | 107 +++++++++++++--------- 4 files changed, 77 insertions(+), 46 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 20da46187..cc4fc6b1c 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -586,6 +586,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("IconsDir", "icons"); m_settings->registerSetting("DownloadsDir", QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); m_settings->registerSetting("DownloadsDirWatchRecursive", false); + m_settings->registerSetting("JavaDir", "java"); // Editors m_settings->registerSetting("JsonEditor", QString()); @@ -1832,5 +1833,5 @@ QUrl Application::normalizeImportUrl(QString const& url) } const QString Application::javaPath() { - return FS::PathCombine(m_dataPath, "java"); + return m_settings->get("JavaDir").toString(); } diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 78c44380a..99a80d98c 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -173,6 +173,16 @@ void LauncherPage::on_downloadsDirBrowseBtn_clicked() } } +void LauncherPage::on_javaDirBrowseBtn_clicked() +{ + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Java Folder"), ui->javaDirTextBox->text()); + + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { + QString cooked_dir = FS::NormalizePath(raw_dir); + ui->javaDirTextBox->setText(cooked_dir); + } +} + void LauncherPage::on_metadataDisableBtn_clicked() { ui->metadataWarningLabel->setHidden(!ui->metadataDisableBtn->isChecked()); @@ -208,6 +218,7 @@ void LauncherPage::applySettings() s->set("CentralModsDir", ui->modsDirTextBox->text()); s->set("IconsDir", ui->iconsDirTextBox->text()); s->set("DownloadsDir", ui->downloadsDirTextBox->text()); + s->set("JavaDir", ui->javaDirTextBox->text()); s->set("DownloadsDirWatchRecursive", ui->downloadsDirWatchRecursiveCheckBox->isChecked()); auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId(); @@ -269,6 +280,7 @@ void LauncherPage::loadSettings() ui->modsDirTextBox->setText(s->get("CentralModsDir").toString()); ui->iconsDirTextBox->setText(s->get("IconsDir").toString()); ui->downloadsDirTextBox->setText(s->get("DownloadsDir").toString()); + ui->javaDirTextBox->setText(s->get("JavaDir").toString()); ui->downloadsDirWatchRecursiveCheckBox->setChecked(s->get("DownloadsDirWatchRecursive").toBool()); QString sortMode = s->get("InstSortMode").toString(); diff --git a/launcher/ui/pages/global/LauncherPage.h b/launcher/ui/pages/global/LauncherPage.h index e733224d2..32945626f 100644 --- a/launcher/ui/pages/global/LauncherPage.h +++ b/launcher/ui/pages/global/LauncherPage.h @@ -74,6 +74,7 @@ class LauncherPage : public QWidget, public BasePage { void on_modsDirBrowseBtn_clicked(); void on_iconsDirBrowseBtn_clicked(); void on_downloadsDirBrowseBtn_clicked(); + void on_javaDirBrowseBtn_clicked(); void on_metadataDisableBtn_clicked(); /*! diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 18b52e1b8..81acb0a17 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -7,7 +7,7 @@ 0 0 511 - 629 + 654 @@ -67,13 +67,20 @@ Folders - - + + - &Downloads: + Browse - - downloadsDirTextBox + + + + + + When enabled, in addition to the downloads folder, its sub folders will also be searched when looking for resources (e.g. when looking for blocked mods on CurseForge). + + + Check downloads folder recursively @@ -87,25 +94,52 @@ - - - - - - - - - - + Browse + + + + + + + Browse + + + + + + + + + + + + + &Icons: + + + iconsDirTextBox + + + + + + + &Downloads: + + + downloadsDirTextBox + + + @@ -123,40 +157,23 @@ - - + + + + Java: + + + + + + + + Browse - - - - Browse - - - - - - - &Icons: - - - iconsDirTextBox - - - - - - - When enabled, in addition to the downloads folder, its sub folders will also be searched when looking for resources (e.g. when looking for blocked mods on CurseForge). - - - Check downloads folder recursively - - -
From b3fc07d44478aa7fc841c88fe9160c462b05577a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Feb 2024 21:47:59 +0200 Subject: [PATCH 036/120] Added extra java search paths Signed-off-by: Trial97 --- launcher/Application.cpp | 1 + launcher/java/JavaUtils.cpp | 27 ++++++++--- launcher/ui/pages/global/JavaPage.cpp | 29 ++++++++++- launcher/ui/pages/global/JavaPage.h | 5 +- launcher/ui/pages/global/JavaPage.ui | 69 +++++++++++++++++++++++++-- 5 files changed, 119 insertions(+), 12 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index cc4fc6b1c..d9abccfdc 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -629,6 +629,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("JvmArgs", ""); m_settings->registerSetting("IgnoreJavaCompatibility", false); m_settings->registerSetting("IgnoreJavaWizard", false); + m_settings->registerSetting("JavaExtraSearchPaths", QStringList()); // Legacy settings m_settings->registerSetting("OnlineFixes", false); diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index ff5ba5efe..cd9593980 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -492,21 +492,34 @@ QStringList getMinecraftJavaBundle() QStringList getPrismJavaBundle() { QList javas; - QDir dir(APPLICATION->javaPath()); - if (!dir.exists()) - return javas; QString executable = "java"; #if defined(Q_OS_WIN32) executable += "w.exe"; #endif - auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); - for (auto& entry : entries) { - QString prefix; - prefix = entry.canonicalFilePath(); + auto scanDir = [&](QString prefix) { javas.append(FS::PathCombine(prefix, "jre", "bin", executable)); javas.append(FS::PathCombine(prefix, "bin", executable)); + javas.append(FS::PathCombine(prefix, executable)); + }; + auto scanJavaDir = [&](const QString& dirPath) { + QDir dir(dirPath); + if (!dir.exists()) + return; + auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (auto& entry : entries) { + scanDir(entry.canonicalFilePath()); + } + }; + + scanJavaDir(APPLICATION->javaPath()); + + auto extra_paths = APPLICATION->settings()->get("JavaExtraSearchPaths").toStringList(); + for (auto& entry : extra_paths) { + scanDir(entry); + scanJavaDir(entry); } + return javas; } diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 9b21aad72..6d278983d 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "ui/dialogs/VersionSelectDialog.h" @@ -57,7 +58,6 @@ JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) { ui->setupUi(this); - ui->tabWidget->tabBar()->hide(); loadSettings(); updateThresholds(); @@ -95,6 +95,7 @@ void JavaPage::applySettings() s->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " ")); s->set("IgnoreJavaCompatibility", ui->skipCompatibilityCheckbox->isChecked()); s->set("IgnoreJavaWizard", ui->skipJavaWizardCheckbox->isChecked()); + s->set("JavaExtraSearchPaths", m_extra_paths->stringList()); JavaCommon::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget()); } void JavaPage::loadSettings() @@ -117,6 +118,8 @@ void JavaPage::loadSettings() ui->jvmArgsTextBox->setPlainText(s->get("JvmArgs").toString()); ui->skipCompatibilityCheckbox->setChecked(s->get("IgnoreJavaCompatibility").toBool()); ui->skipJavaWizardCheckbox->setChecked(s->get("IgnoreJavaWizard").toBool()); + m_extra_paths = new QStringListModel(s->get("JavaExtraSearchPaths").toStringList()); + ui->extraJavaPathsList->setModel(m_extra_paths); } void JavaPage::on_javaDetectBtn_clicked() @@ -217,3 +220,27 @@ void JavaPage::updateThresholds() ui->labelMaxMemIcon->setPixmap(pix); } } + +void JavaPage::on_addExtraPathButton_clicked() +{ + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Add Extra Java Folder")); + + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { + QString cooked_dir = FS::NormalizePath(raw_dir); + auto currentList = m_extra_paths->stringList(); + if (!currentList.contains(cooked_dir)) { + currentList << cooked_dir; + m_extra_paths->setStringList(currentList); + } + } + APPLICATION->settings()->set("JavaExtraSearchPaths", m_extra_paths->stringList()); +} + +void JavaPage::on_removeExtraPathButton_clicked() +{ + auto indexes = ui->extraJavaPathsList->selectionModel()->selectedIndexes(); + if (indexes.size()) { + m_extra_paths->removeRow(indexes.first().row()); + } + APPLICATION->settings()->set("JavaExtraSearchPaths", m_extra_paths->stringList()); +} diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h index 2bbfdf6bf..d1315db64 100644 --- a/launcher/ui/pages/global/JavaPage.h +++ b/launcher/ui/pages/global/JavaPage.h @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "JavaCommon.h" #include "ui/pages/BasePage.h" @@ -73,10 +73,13 @@ class JavaPage : public QWidget, public BasePage { void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); void on_javaDownloadBtn_clicked(); + void on_addExtraPathButton_clicked(); + void on_removeExtraPathButton_clicked(); void on_maxMemSpinBox_valueChanged(int i); void checkerFinished(); private: Ui::JavaPage* ui; unique_qobject_ptr checker; + QStringListModel* m_extra_paths; }; diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index 382c183c9..d57e2e548 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -32,11 +32,11 @@ - 0 + 1 - + - Tab 1 + General @@ -312,6 +312,69 @@ + + + Management + + + + + + Java extra paths + + + + + + + + + + + Add + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + +
From 379f1a70e99a9a629c3cb174a1ad596fcb79a3cb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Feb 2024 22:37:57 +0200 Subject: [PATCH 037/120] Leave headers alone Signed-off-by: Trial97 --- launcher/Application.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index d9abccfdc..498427856 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -48,6 +48,7 @@ #include "net/PasteUpload.h" #include "pathmatcher/MultiMatcher.h" #include "pathmatcher/SimplePrefixMatcher.h" +#include "settings/INIFile.h" #include "ui/InstanceWindow.h" #include "ui/MainWindow.h" @@ -105,6 +106,8 @@ #include "icons/IconList.h" #include "net/HttpMetaCache.h" +#include "java/JavaUtils.h" + #include "updater/ExternalUpdater.h" #include "tools/JProfiler.h" From 0a3303bcbdabbc2e5e1338dabfb3b8cf518d29e4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 9 Feb 2024 21:07:12 +0200 Subject: [PATCH 038/120] Added button to add extra java path to the Java Wizzard Signed-off-by: Trial97 --- launcher/ui/dialogs/VersionSelectDialog.h | 4 ---- launcher/ui/widgets/JavaSettingsWidget.cpp | 27 ++++++++++++++++++++-- launcher/ui/widgets/JavaSettingsWidget.h | 5 +++- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/launcher/ui/dialogs/VersionSelectDialog.h b/launcher/ui/dialogs/VersionSelectDialog.h index 0ccd45e74..17efc1b93 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.h +++ b/launcher/ui/dialogs/VersionSelectDialog.h @@ -26,10 +26,6 @@ class QDialogButtonBox; class VersionSelectWidget; class QPushButton; -namespace Ui { -class VersionSelectDialog; -} - class VersionProxyModel; class VersionSelectDialog : public QDialog { diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 3f4fe08ea..bb57e5da7 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -42,6 +42,7 @@ JavaSettingsWidget::JavaSettingsWidget(QWidget* parent) : QWidget(parent) connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaSettingsWidget::javaPathEdited); connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaSettingsWidget::on_javaStatusBtn_clicked); connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaDownloadBtn_clicked); + connect(m_addJavaPathBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_addJavaPathBtn_clicked); } void JavaSettingsWidget::setupUi() @@ -124,9 +125,16 @@ void JavaSettingsWidget::setupUi() m_verticalLayout->addWidget(m_memoryGroupBox); - m_javaDownloadBtn = new QPushButton(tr("Download Java"), this); + m_horizontalBtnLayout = new QHBoxLayout(); + m_horizontalBtnLayout->setObjectName(QStringLiteral("horizontalBtnLayout")); - m_verticalLayout->addWidget(m_javaDownloadBtn); + m_javaDownloadBtn = new QPushButton(tr("Download Java"), this); + m_horizontalBtnLayout->addWidget(m_javaDownloadBtn); + + m_addJavaPathBtn = new QPushButton(tr("Add extra Java path"), this); + m_horizontalBtnLayout->addWidget(m_addJavaPathBtn); + + m_verticalLayout->addLayout(m_horizontalBtnLayout); retranslate(); } @@ -437,3 +445,18 @@ void JavaSettingsWidget::updateThresholds() m_labelMaxMemIcon->setPixmap(pix); } } + +void JavaSettingsWidget::on_addJavaPathBtn_clicked() +{ + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Add Extra Java Folder")); + + auto currentList = APPLICATION->settings()->get("JavaExtraSearchPaths").toStringList(); + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { + QString cooked_dir = FS::NormalizePath(raw_dir); + if (!currentList.contains(cooked_dir)) { + currentList << cooked_dir; + } + } + APPLICATION->settings()->set("JavaExtraSearchPaths", currentList); + refresh(); +} diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index b7db955a4..385a9256a 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -25,7 +25,7 @@ class JavaSettingsWidget : public QWidget { public: explicit JavaSettingsWidget(QWidget* parent); - virtual ~JavaSettingsWidget(){}; + virtual ~JavaSettingsWidget() = default; enum class JavaStatus { NotSet, Pending, Good, DoesNotExist, DoesNotStart, ReturnedInvalidData } javaStatus = JavaStatus::NotSet; @@ -51,6 +51,7 @@ class JavaSettingsWidget : public QWidget { void on_javaBrowseBtn_clicked(); void on_javaStatusBtn_clicked(); void on_javaDownloadBtn_clicked(); + void on_addJavaPathBtn_clicked(); void checkFinished(const JavaChecker::Result& result); protected: /* methods */ @@ -78,7 +79,9 @@ class JavaSettingsWidget : public QWidget { QLabel* m_labelPermGen = nullptr; QSpinBox* m_permGenSpinBox = nullptr; + QHBoxLayout* m_horizontalBtnLayout = nullptr; QPushButton* m_javaDownloadBtn = nullptr; + QPushButton* m_addJavaPathBtn = nullptr; QIcon goodIcon; QIcon yellowIcon; QIcon badIcon; From 27d662e64241a75eee963048a669398a5083f7ed Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 9 Feb 2024 22:47:39 +0200 Subject: [PATCH 039/120] Added management for downloaded javas from prism Signed-off-by: Trial97 --- launcher/java/JavaInstallList.cpp | 10 +++-- launcher/java/JavaInstallList.h | 6 ++- launcher/java/JavaUtils.cpp | 31 ++++++++++++++ launcher/java/JavaUtils.h | 1 + launcher/ui/pages/global/JavaPage.cpp | 40 ++++++++++++++++++ launcher/ui/pages/global/JavaPage.h | 2 + launcher/ui/pages/global/JavaPage.ui | 60 ++++++++++++++++++++++++++- 7 files changed, 143 insertions(+), 7 deletions(-) diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index d99201f24..4172ba2cf 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -46,7 +46,9 @@ #include "java/JavaUtils.h" #include "tasks/ConcurrentTask.h" -JavaInstallList::JavaInstallList(QObject* parent) : BaseVersionList(parent) {} +JavaInstallList::JavaInstallList(QObject* parent, bool onlyManagedVersions) + : BaseVersionList(parent), m_only_managed_versions(onlyManagedVersions) +{} Task::Ptr JavaInstallList::getLoadTask() { @@ -66,7 +68,7 @@ void JavaInstallList::load() { if (m_status != Status::InProgress) { m_status = Status::InProgress; - m_load_task.reset(new JavaListLoadTask(this)); + m_load_task.reset(new JavaListLoadTask(this, m_only_managed_versions)); m_load_task->start(); } } @@ -148,7 +150,7 @@ void JavaInstallList::sortVersions() endResetModel(); } -JavaListLoadTask::JavaListLoadTask(JavaInstallList* vlist) : Task() +JavaListLoadTask::JavaListLoadTask(JavaInstallList* vlist, bool onlyManagedVersions) : Task(), m_only_managed_versions(onlyManagedVersions) { m_list = vlist; m_current_recommended = NULL; @@ -159,7 +161,7 @@ void JavaListLoadTask::executeTask() setStatus(tr("Detecting Java installations...")); JavaUtils ju; - QList candidate_paths = ju.FindJavaPaths(); + QList candidate_paths = m_only_managed_versions ? getPrismJavaBundle() : ju.FindJavaPaths(); ConcurrentTask::Ptr job(new ConcurrentTask(this, "Java detection", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())); m_job.reset(job); diff --git a/launcher/java/JavaInstallList.h b/launcher/java/JavaInstallList.h index 08f0b310d..c68c2a3be 100644 --- a/launcher/java/JavaInstallList.h +++ b/launcher/java/JavaInstallList.h @@ -33,7 +33,7 @@ class JavaInstallList : public BaseVersionList { enum class Status { NotDone, InProgress, Done }; public: - explicit JavaInstallList(QObject* parent = 0); + explicit JavaInstallList(QObject* parent = 0, bool onlyManagedVersions = false); Task::Ptr getLoadTask() override; bool isLoaded() override; @@ -55,13 +55,14 @@ class JavaInstallList : public BaseVersionList { Status m_status = Status::NotDone; shared_qobject_ptr m_load_task; QList m_vlist; + bool m_only_managed_versions; }; class JavaListLoadTask : public Task { Q_OBJECT public: - explicit JavaListLoadTask(JavaInstallList* vlist); + explicit JavaListLoadTask(JavaInstallList* vlist, bool onlyManagedVersions = false); virtual ~JavaListLoadTask() = default; protected: @@ -74,4 +75,5 @@ class JavaListLoadTask : public Task { JavaInstallList* m_list; JavaInstall* m_current_recommended; QList m_results; + bool m_only_managed_versions; }; diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index cd9593980..1d254e405 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -338,6 +338,7 @@ QList JavaUtils::FindJavaPaths() candidates.append(getMinecraftJavaBundle()); candidates.append(getPrismJavaBundle()); + candidates.append(getPrismExtraJavaPaths()); candidates = addJavasFromEnv(candidates); candidates.removeDuplicates(); return candidates; @@ -365,6 +366,7 @@ QList JavaUtils::FindJavaPaths() } javas.append(getMinecraftJavaBundle()); javas.append(getPrismJavaBundle()); + javas.append(getPrismExtraJavaPaths()); javas = addJavasFromEnv(javas); javas.removeDuplicates(); return javas; @@ -418,6 +420,7 @@ QList JavaUtils::FindJavaPaths() javas.append(getMinecraftJavaBundle()); javas.append(getPrismJavaBundle()); + javas.append(getPrismExtraJavaPaths()); javas = addJavasFromEnv(javas); javas.removeDuplicates(); return javas; @@ -432,6 +435,7 @@ QList JavaUtils::FindJavaPaths() javas.append(getMinecraftJavaBundle()); javas.append(getPrismJavaBundle()); + javas.append(getPrismExtraJavaPaths()); javas.removeDuplicates(); return addJavasFromEnv(javas); } @@ -515,6 +519,33 @@ QStringList getPrismJavaBundle() scanJavaDir(APPLICATION->javaPath()); + return javas; +} + +QStringList getPrismExtraJavaPaths() +{ + QList javas; + + QString executable = "java"; +#if defined(Q_OS_WIN32) + executable += "w.exe"; +#endif + + auto scanDir = [&](QString prefix) { + javas.append(FS::PathCombine(prefix, "jre", "bin", executable)); + javas.append(FS::PathCombine(prefix, "bin", executable)); + javas.append(FS::PathCombine(prefix, executable)); + }; + auto scanJavaDir = [&](const QString& dirPath) { + QDir dir(dirPath); + if (!dir.exists()) + return; + auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (auto& entry : entries) { + scanDir(entry.canonicalFilePath()); + } + }; + auto extra_paths = APPLICATION->settings()->get("JavaExtraSearchPaths").toStringList(); for (auto& entry : extra_paths) { scanDir(entry); diff --git a/launcher/java/JavaUtils.h b/launcher/java/JavaUtils.h index aa5315a19..66e439834 100644 --- a/launcher/java/JavaUtils.h +++ b/launcher/java/JavaUtils.h @@ -27,6 +27,7 @@ QString stripVariableEntries(QString name, QString target, QString remove); QProcessEnvironment CleanEnviroment(); QStringList getMinecraftJavaBundle(); QStringList getPrismJavaBundle(); +QStringList getPrismExtraJavaPaths(); class JavaUtils : public QObject { Q_OBJECT diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 6d278983d..7d7530e35 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -36,6 +36,8 @@ #include "JavaPage.h" #include "JavaCommon.h" +#include "java/JavaInstall.h" +#include "ui/dialogs/CustomMessageBox.h" #include "ui/java/JavaDownloader.h" #include "ui_JavaPage.h" @@ -59,6 +61,11 @@ JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) { ui->setupUi(this); + ui->managedJavaList->initialize(new JavaInstallList(this, true)); + ui->managedJavaList->selectCurrent(); + ui->managedJavaList->setEmptyString(tr("No java versions are currently available in the meta")); + ui->managedJavaList->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); + loadSettings(); updateThresholds(); } @@ -244,3 +251,36 @@ void JavaPage::on_removeExtraPathButton_clicked() } APPLICATION->settings()->set("JavaExtraSearchPaths", m_extra_paths->stringList()); } + +void JavaPage::on_downloadJavaButton_clicked() +{ + on_javaDownloadBtn_clicked(); +} + +void JavaPage::on_removeJavaButton_clicked() +{ + auto version = ui->managedJavaList->selectedVersion(); + auto dcast = std::dynamic_pointer_cast(version); + if (!dcast) { + return; + } + QDir dir(APPLICATION->javaPath()); + + auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (auto& entry : entries) { + if (dcast->path.startsWith(entry.canonicalFilePath())) { + auto response = CustomMessageBox::selectable(this, tr("Confirm Deletion"), + tr("You are about to remove \"%1\" java version.\n" + "Are you sure?") + .arg(entry.fileName()), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response == QMessageBox::Yes) { + FS::deletePath(entry.canonicalFilePath()); + ui->managedJavaList->loadList(); + } + break; + } + } +} diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h index d1315db64..03d14b824 100644 --- a/launcher/ui/pages/global/JavaPage.h +++ b/launcher/ui/pages/global/JavaPage.h @@ -75,6 +75,8 @@ class JavaPage : public QWidget, public BasePage { void on_javaDownloadBtn_clicked(); void on_addExtraPathButton_clicked(); void on_removeExtraPathButton_clicked(); + void on_downloadJavaButton_clicked(); + void on_removeJavaButton_clicked(); void on_maxMemSpinBox_valueChanged(int i); void checkerFinished(); diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index d57e2e548..a518b0b14 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -32,7 +32,7 @@ - 1 + 0 @@ -317,6 +317,56 @@ Management + + + + Downloaded Java Versions + + + + + + + 0 + 0 + + + + + + + + + + Download + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + @@ -379,6 +429,14 @@ + + + VersionSelectWidget + QWidget +
ui/widgets/VersionSelectWidget.h
+ 1 +
+
minMemSpinBox maxMemSpinBox From c0fb053ccc966045df42e8b218a994cfcfdef986 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 9 Feb 2024 23:14:49 +0200 Subject: [PATCH 040/120] Added warning for x86 java Signed-off-by: Trial97 --- launcher/java/JavaInstall.h | 1 + launcher/java/JavaInstallList.cpp | 1 + launcher/ui/pages/global/JavaPage.cpp | 8 ++++++++ launcher/ui/pages/instance/InstanceSettingsPage.cpp | 10 ++++++++++ launcher/ui/widgets/JavaSettingsWidget.cpp | 4 ++++ 5 files changed, 24 insertions(+) diff --git a/launcher/java/JavaInstall.h b/launcher/java/JavaInstall.h index 8c2743a00..6890264f3 100644 --- a/launcher/java/JavaInstall.h +++ b/launcher/java/JavaInstall.h @@ -40,6 +40,7 @@ struct JavaInstall : public BaseVersion { QString arch; QString path; bool recommended = false; + bool is_64bit = false; }; using JavaInstallPtr = std::shared_ptr; diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index 4172ba2cf..569fda306 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -193,6 +193,7 @@ void JavaListLoadTask::javaCheckerFinished() javaVersion->id = result.javaVersion; javaVersion->arch = result.realPlatform; javaVersion->path = result.path; + javaVersion->is_64bit = result.is_64bit; candidates.append(javaVersion); qDebug() << " " << javaVersion->id.toString() << javaVersion->arch << javaVersion->path; diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 7d7530e35..9b2aa7637 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -145,6 +145,14 @@ void JavaPage::on_javaDetectBtn_clicked() if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) { java = std::dynamic_pointer_cast(vselect.selectedVersion()); ui->javaPathTextBox->setText(java->path); + if (!java->is_64bit && APPLICATION->settings()->get("MaxMemAlloc").toInt() > 2048) { + CustomMessageBox::selectable(this, tr("Confirm Selection"), + tr("You selected an x86 java version.\n" + "This means that will not support more than 2Gb(2048Mb) of ram.\n" + "Please make sure that the maximum memory value is lower."), + QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok) + ->exec(); + } } } diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index b962406d1..926e48952 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -36,6 +36,7 @@ */ #include "InstanceSettingsPage.h" +#include "ui/dialogs/CustomMessageBox.h" #include "ui/java/JavaDownloader.h" #include "ui_InstanceSettingsPage.h" @@ -412,6 +413,15 @@ void InstanceSettingsPage::on_javaDetectBtn_clicked() ui->labelPermGen->setVisible(visible); ui->labelPermgenNote->setVisible(visible); m_settings->set("PermGenVisible", visible); + + if (!java->is_64bit && m_settings->get("MaxMemAlloc").toInt() > 2048) { + CustomMessageBox::selectable(this, tr("Confirm Selection"), + tr("You selected an x86 java version.\n" + "This means that will not support more than 2Gb(2048Mb) of ram.\n" + "Please make sure that the maximum memory value is lower."), + QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok) + ->exec(); + } } } diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index bb57e5da7..507c632d5 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -433,6 +433,10 @@ void JavaSettingsWidget::updateThresholds() } else if (observedMaxMemory < observedMinMemory) { iconName = "status-yellow"; m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value")); + } else if (observedMaxMemory > 2048 && m_result.is_64bit) { + iconName = "status-bad"; + m_labelMaxMemIcon->setToolTip( + tr("Your maximum memory allocation exceeds selected java posible memory(due to x86 applicatiion limitations).")); } else { iconName = "status-good"; m_labelMaxMemIcon->setToolTip(""); From 2941307581114c435a2950df59e8ddc2c3c7c0c4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 16 Feb 2024 23:42:39 +0200 Subject: [PATCH 041/120] Added basic java auto-detect and auto-download Signed-off-by: Trial97 --- launcher/Application.cpp | 2 + launcher/CMakeLists.txt | 2 + launcher/minecraft/MinecraftInstance.cpp | 12 +- launcher/minecraft/launch/AutoInstallJava.cpp | 192 ++++++++++++++++++ launcher/minecraft/launch/AutoInstallJava.h | 67 ++++++ .../minecraft/launch/VerifyJavaInstall.cpp | 45 +--- launcher/ui/pages/global/JavaPage.cpp | 4 + launcher/ui/pages/global/JavaPage.ui | 66 +++--- 8 files changed, 325 insertions(+), 65 deletions(-) create mode 100644 launcher/minecraft/launch/AutoInstallJava.cpp create mode 100644 launcher/minecraft/launch/AutoInstallJava.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 498427856..6b7333972 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -633,6 +633,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("IgnoreJavaCompatibility", false); m_settings->registerSetting("IgnoreJavaWizard", false); m_settings->registerSetting("JavaExtraSearchPaths", QStringList()); + m_settings->registerSetting("AutomaticJavaSwitch", false); + m_settings->registerSetting("AutomaticJavaDownload", false); // Legacy settings m_settings->registerSetting("OnlineFixes", false); diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index c7945d1b8..fcc3c2f3a 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -281,6 +281,8 @@ set(MINECRAFT_SOURCES minecraft/launch/ScanModFolders.h minecraft/launch/VerifyJavaInstall.cpp minecraft/launch/VerifyJavaInstall.h + minecraft/launch/AutoInstallJava.cpp + minecraft/launch/AutoInstallJava.h minecraft/GradleSpecifier.h minecraft/MinecraftInstance.cpp diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 4229f73eb..00ce405aa 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -38,6 +38,8 @@ #include "MinecraftInstance.h" #include "Application.h" #include "BuildConfig.h" +#include "QObjectPtr.h" +#include "minecraft/launch/AutoInstallJava.h" #include "minecraft/launch/CreateGameFolders.h" #include "minecraft/launch/ExtractNatives.h" #include "minecraft/launch/PrintInstanceInfo.h" @@ -1041,11 +1043,6 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(makeShared(pptr, "Minecraft folder is:\n" + gameRoot() + "\n\n", MessageLevel::Launcher)); } - // check java - { - process->appendStep(makeShared(pptr)); - } - // create the .minecraft folder and server-resource-packs (workaround for Minecraft bug MCL-3732) { process->appendStep(makeShared(pptr)); @@ -1105,6 +1102,11 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt { process->appendStep(makeShared(pptr)); } + // check java + { + process->appendStep(makeShared(pptr)); + process->appendStep(makeShared(pptr)); + } // verify that minimum Java requirements are met { diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp new file mode 100644 index 000000000..0d3740c93 --- /dev/null +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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 "AutoInstallJava.h" +#include +#include +#include + +#include "Application.h" +#include "FileSystem.h" +#include "MessageLevel.h" +#include "SysInfo.h" +#include "java/JavaInstall.h" +#include "java/JavaInstallList.h" +#include "java/JavaVersion.h" +#include "java/download/ArchiveDownloadTask.h" +#include "java/download/ManifestDownloadTask.h" +#include "meta/Index.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/PackProfile.h" +#include "net/Mode.h" + +AutoInstallJava::AutoInstallJava(LaunchTask* parent) + : LaunchStep(parent) + , m_instance(std::dynamic_pointer_cast(m_parent->instance())) + , m_supported_arch(SysInfo::getSupportedJavaArchitecture()){}; + +void AutoInstallJava::executeTask() +{ + auto settings = m_instance->settings(); + if (!APPLICATION->settings()->get("AutomaticJavaSwitch").toBool() || + (settings->get("OverrideJava").toBool() && settings->get("OverrideJavaLocation").toBool())) { + emitSucceeded(); + return; + } + auto packProfile = m_instance->getPackProfile(); + if (!APPLICATION->settings()->get("AutomaticJavaDownload").toBool()) { + auto javas = APPLICATION->javalist().get(); + 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(javas->at(i)); + if (java && packProfile->getProfile()->getCompatibleJavaMajors().contains(java->id.major())) { + setJavaPath(java->path); + return; + } + } + emit logLine(tr("No comptatible java version was found. Using the default one."), MessageLevel::Warning); + emitSucceeded(); + }); + return; + } + auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName(); + QDir javaDir(APPLICATION->javaPath()); + auto wantedJavaPath = javaDir.absoluteFilePath(wantedJavaName); + if (QFileInfo::exists(wantedJavaPath)) { + setJavaPathFromPartial(); + return; + } + auto versionList = APPLICATION->metadataIndex()->get("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); +} + +void AutoInstallJava::setJavaPath(QString path) +{ + auto settings = m_instance->settings(); + settings->set("OverrideJava", true); + settings->set("OverrideJavaLocation", true); + settings->set("JavaPath", path); + emit logLine(tr("Compatible java found at: %1.").arg(path), MessageLevel::Info); + emitSucceeded(); +} + +void AutoInstallJava::setJavaPathFromPartial() +{ + QString executable = "java"; +#if defined(Q_OS_WIN32) + executable += "w.exe"; +#endif + 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", executable); + auto finalPath = javaDir.absoluteFilePath(relativeBinary); + if (QFileInfo::exists(finalPath)) { + setJavaPath(finalPath); + } else { + emit logLine(tr("No comptatible java version was found. Using the default one."), MessageLevel::Warning); + emitSucceeded(); + } + return; +} + +void AutoInstallJava::downloadJava(Meta::Version::Ptr version, QString javaName) +{ + auto runtimes = version->data()->runtimes; + if (runtimes.contains(m_supported_arch)) { + for (auto java : runtimes.value(m_supported_arch)) { + if (java->name() == javaName) { + Task::Ptr task; + QDir javaDir(APPLICATION->javaPath()); + auto final_path = javaDir.absoluteFilePath(java->m_name); + switch (java->downloadType) { + case Java::DownloadType::Manifest: + task = makeShared(java->url, final_path, java->checksumType, java->checksumHash); + break; + case Java::DownloadType::Archive: + task = makeShared(java->url, final_path, java->checksumType, java->checksumHash); + break; + } + QEventLoop loop; + auto deletePath = [final_path] { FS::deletePath(final_path); }; + connect(task.get(), &Task::failed, this, [this, deletePath](QString reason) { + deletePath(); + emitFailed(reason); + }); + connect(this, &Task::aborted, this, [task, deletePath] { + task->abort(); + deletePath(); + }); + connect(task.get(), &Task::succeeded, this, &AutoInstallJava::setJavaPathFromPartial); + task->start(); + return; + } + } + } + tryNextMajorJava(); +} + +void AutoInstallJava::tryNextMajorJava() +{ + if (!isRunning()) + return; + auto versionList = APPLICATION->metadataIndex()->get("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 comptatible java version was found. Using the default one."), MessageLevel::Warning); + emitSucceeded(); + return; + } + auto majorJavaVersion = majorJavaVersions[m_majorJavaVersionIndex]; + m_majorJavaVersionIndex++; + + auto javaMajor = versionList->getVersion(QString("java%1").arg(majorJavaVersion)); + javaMajor->load(Net::Mode::Online); + auto task = javaMajor->getCurrentTask(); + if (javaMajor->isLoaded() || !task) { + downloadJava(javaMajor, wantedJavaName); + } else { + connect(task.get(), &Task::succeeded, this, [this, javaMajor, wantedJavaName] { downloadJava(javaMajor, wantedJavaName); }); + connect(task.get(), &Task::failed, this, &AutoInstallJava::tryNextMajorJava); + } +} diff --git a/launcher/minecraft/launch/AutoInstallJava.h b/launcher/minecraft/launch/AutoInstallJava.h new file mode 100644 index 000000000..4dcd3796a --- /dev/null +++ b/launcher/minecraft/launch/AutoInstallJava.h @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + */ + +#pragma once + +#include +#include +#include "java/JavaMetadata.h" +#include "meta/Version.h" +#include "minecraft/MinecraftInstance.h" +#include "tasks/Task.h" + +class AutoInstallJava : public LaunchStep { + Q_OBJECT + + public: + explicit AutoInstallJava(LaunchTask* parent); + ~AutoInstallJava() override = default; + + void executeTask() override; + bool canAbort() const override { return m_current_task ? m_current_task->canAbort() : false; } + + protected: + void setJavaPath(QString path); + void setJavaPathFromPartial(); + void downloadJava(Meta::Version::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/launcher/minecraft/launch/VerifyJavaInstall.cpp b/launcher/minecraft/launch/VerifyJavaInstall.cpp index 218811290..279545fed 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.cpp +++ b/launcher/minecraft/launch/VerifyJavaInstall.cpp @@ -50,7 +50,6 @@ void VerifyJavaInstall::executeTask() auto settings = instance->settings(); auto storedVersion = settings->get("JavaVersion").toString(); auto ignoreCompatibility = settings->get("IgnoreJavaCompatibility").toBool(); - auto automaticJavaSwitch = settings->get("AutomaticJavaSwitch").toBool(); auto compatibleMajors = packProfile->getProfile()->getCompatibleJavaMajors(); @@ -67,38 +66,16 @@ void VerifyJavaInstall::executeTask() return; } - auto logFail = [this, &javaVersion, compatibleMajors] { - 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")); - }; - - if (automaticJavaSwitch || true) { - settings->set("OverrideJava", true); - auto javas = APPLICATION->javalist().get(); - auto task = javas->getLoadTask(); - connect(task.get(), &Task::finished, this, [this, javas, compatibleMajors, settings, &logFail] { - for (auto i = 0; i < javas->count(); i++) { - auto java = std::dynamic_pointer_cast(javas->at(i)); - if (java && compatibleMajors.contains(java->id.major())) { - settings->set("OverrideJavaLocation", true); - settings->set("JavaPath", java->path); - emitSucceeded(); - return; - } - } - logFail(); - }); - } else { - logFail(); + 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/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 9b2aa7637..496cb69a7 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -102,6 +102,8 @@ void JavaPage::applySettings() s->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " ")); s->set("IgnoreJavaCompatibility", ui->skipCompatibilityCheckbox->isChecked()); s->set("IgnoreJavaWizard", ui->skipJavaWizardCheckbox->isChecked()); + s->set("AutomaticJavaSwitch", ui->autodetectJavaCheckBox->isChecked()); + s->set("AutomaticJavaDownload", ui->autodownloadCheckBox->isChecked()); s->set("JavaExtraSearchPaths", m_extra_paths->stringList()); JavaCommon::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget()); } @@ -125,6 +127,8 @@ void JavaPage::loadSettings() ui->jvmArgsTextBox->setPlainText(s->get("JvmArgs").toString()); ui->skipCompatibilityCheckbox->setChecked(s->get("IgnoreJavaCompatibility").toBool()); ui->skipJavaWizardCheckbox->setChecked(s->get("IgnoreJavaWizard").toBool()); + ui->autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); + ui->autodownloadCheckBox->setChecked(s->get("AutomaticJavaDownload").toBool()); m_extra_paths = new QStringListModel(s->get("JavaExtraSearchPaths").toStringList()); ui->extraJavaPathsList->setModel(m_extra_paths); } diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index a518b0b14..d135adc9a 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -160,25 +160,6 @@ Java Runtime - - - - true - - - - 0 - 0 - - - - - 16777215 - 100 - - - - @@ -232,7 +213,7 @@
- + @@ -248,6 +229,42 @@ + + + + If enabled, the launcher will not prompt you to choose a Java version if one isn't found. + + + Skip Java &Wizard + + + + + + + true + + + + 0 + 0 + + + + + 16777215 + 100 + + + + + + + + Autodetect Java version + + + @@ -284,13 +301,10 @@ - - - - If enabled, the launcher will not prompt you to choose a Java version if one isn't found. - + + - Skip Java &Wizard + Autodownload Mojang Java From ea2adf909dfe10c0adaf53ef2fabbd94ee7ae8cd Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 17 Feb 2024 11:14:32 +0200 Subject: [PATCH 042/120] Added progeess dialog to autodownload java Signed-off-by: Trial97 --- .../java/download/ArchiveDownloadTask.cpp | 5 +- .../java/download/ManifestDownloadTask.cpp | 10 +++- launcher/minecraft/launch/AutoInstallJava.cpp | 59 ++++++++++++++----- launcher/minecraft/launch/AutoInstallJava.h | 1 + 4 files changed, 56 insertions(+), 19 deletions(-) diff --git a/launcher/java/download/ArchiveDownloadTask.cpp b/launcher/java/download/ArchiveDownloadTask.cpp index 847f3f364..9f8dc0543 100644 --- a/launcher/java/download/ArchiveDownloadTask.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -50,9 +50,12 @@ void ArchiveDownloadTask::executeTask() auto fullPath = entry->getFullPath(); connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); - connect(download.get(), &NetJob::progress, this, &ArchiveDownloadTask::progress); connect(download.get(), &NetJob::failed, this, &ArchiveDownloadTask::emitFailed); connect(this, &Task::aborted, download.get(), &NetJob::abort); + connect(download.get(), &Task::progress, this, &ArchiveDownloadTask::setProgress); + connect(download.get(), &Task::stepProgress, this, &ArchiveDownloadTask::propagateStepProgress); + connect(download.get(), &Task::status, this, &ArchiveDownloadTask::setStatus); + connect(download.get(), &Task::details, this, &ArchiveDownloadTask::setDetails); connect(download.get(), &NetJob::succeeded, [this, fullPath] { // This should do all of the extracting and creating folders extractJava(fullPath); diff --git a/launcher/java/download/ManifestDownloadTask.cpp b/launcher/java/download/ManifestDownloadTask.cpp index 1a3071530..0c2eee0c8 100644 --- a/launcher/java/download/ManifestDownloadTask.cpp +++ b/launcher/java/download/ManifestDownloadTask.cpp @@ -52,9 +52,12 @@ void ManifestDownloadTask::executeTask() download->addNetAction(action); connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); - connect(download.get(), &NetJob::progress, this, &ManifestDownloadTask::progress); connect(download.get(), &NetJob::failed, this, &ManifestDownloadTask::emitFailed); connect(this, &Task::aborted, download.get(), &NetJob::abort); + connect(download.get(), &Task::progress, this, &ManifestDownloadTask::setProgress); + connect(download.get(), &Task::stepProgress, this, &ManifestDownloadTask::propagateStepProgress); + connect(download.get(), &Task::status, this, &ManifestDownloadTask::setStatus); + connect(download.get(), &Task::details, this, &ManifestDownloadTask::setDetails); connect(download.get(), &NetJob::succeeded, [files, this] { QJsonParseError parse_error{}; @@ -117,8 +120,11 @@ void ManifestDownloadTask::downloadJava(const QJsonDocument& doc) disconnect(this, &Task::aborted, elementDownload, &NetJob::abort); elementDownload->deleteLater(); }); - connect(elementDownload, &NetJob::progress, this, &ManifestDownloadTask::progress); connect(elementDownload, &NetJob::failed, this, &ManifestDownloadTask::emitFailed); + connect(elementDownload, &Task::progress, this, &ManifestDownloadTask::setProgress); + connect(elementDownload, &Task::stepProgress, this, &ManifestDownloadTask::propagateStepProgress); + connect(elementDownload, &Task::status, this, &ManifestDownloadTask::setStatus); + connect(elementDownload, &Task::details, this, &ManifestDownloadTask::setDetails); connect(this, &Task::aborted, elementDownload, &NetJob::abort); connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index 0d3740c93..d93276432 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -34,8 +34,8 @@ */ #include "AutoInstallJava.h" -#include -#include +#include +#include #include #include "Application.h" @@ -61,7 +61,8 @@ void AutoInstallJava::executeTask() { auto settings = m_instance->settings(); if (!APPLICATION->settings()->get("AutomaticJavaSwitch").toBool() || - (settings->get("OverrideJava").toBool() && settings->get("OverrideJavaLocation").toBool())) { + (settings->get("OverrideJava").toBool() && settings->get("OverrideJavaLocation").toBool() && + QFileInfo::exists(settings->get("JavaPath").toString()))) { emitSucceeded(); return; } @@ -80,6 +81,11 @@ void AutoInstallJava::executeTask() emit logLine(tr("No comptatible 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; } auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName(); @@ -93,6 +99,11 @@ void AutoInstallJava::executeTask() 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); + emit progressReportingRequest(); } void AutoInstallJava::setJavaPath(QString path) @@ -134,29 +145,34 @@ void AutoInstallJava::downloadJava(Meta::Version::Ptr version, QString javaName) if (runtimes.contains(m_supported_arch)) { for (auto java : runtimes.value(m_supported_arch)) { if (java->name() == javaName) { - Task::Ptr task; QDir javaDir(APPLICATION->javaPath()); auto final_path = javaDir.absoluteFilePath(java->m_name); switch (java->downloadType) { case Java::DownloadType::Manifest: - task = makeShared(java->url, final_path, java->checksumType, java->checksumHash); + m_current_task = + makeShared(java->url, final_path, java->checksumType, java->checksumHash); break; case Java::DownloadType::Archive: - task = makeShared(java->url, final_path, java->checksumType, java->checksumHash); + m_current_task = + makeShared(java->url, final_path, java->checksumType, java->checksumHash); break; } - QEventLoop loop; auto deletePath = [final_path] { FS::deletePath(final_path); }; - connect(task.get(), &Task::failed, this, [this, deletePath](QString reason) { + connect(m_current_task.get(), &Task::failed, this, [this, deletePath](QString reason) { deletePath(); emitFailed(reason); }); - connect(this, &Task::aborted, this, [task, deletePath] { - task->abort(); + connect(this, &Task::aborted, this, [this, deletePath] { + m_current_task->abort(); deletePath(); }); - connect(task.get(), &Task::succeeded, this, &AutoInstallJava::setJavaPathFromPartial); - task->start(); + 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; } } @@ -182,11 +198,22 @@ void AutoInstallJava::tryNextMajorJava() auto javaMajor = versionList->getVersion(QString("java%1").arg(majorJavaVersion)); javaMajor->load(Net::Mode::Online); - auto task = javaMajor->getCurrentTask(); - if (javaMajor->isLoaded() || !task) { + m_current_task = javaMajor->getCurrentTask(); + if (javaMajor->isLoaded() || !m_current_task) { downloadJava(javaMajor, wantedJavaName); } else { - connect(task.get(), &Task::succeeded, this, [this, javaMajor, wantedJavaName] { downloadJava(javaMajor, wantedJavaName); }); - connect(task.get(), &Task::failed, this, &AutoInstallJava::tryNextMajorJava); + 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); } } +bool AutoInstallJava::abort() +{ + if (m_current_task && m_current_task->canAbort()) + return m_current_task->abort(); + return true; +} diff --git a/launcher/minecraft/launch/AutoInstallJava.h b/launcher/minecraft/launch/AutoInstallJava.h index 4dcd3796a..45d0f870e 100644 --- a/launcher/minecraft/launch/AutoInstallJava.h +++ b/launcher/minecraft/launch/AutoInstallJava.h @@ -51,6 +51,7 @@ class AutoInstallJava : public LaunchStep { void executeTask() override; bool canAbort() const override { return m_current_task ? m_current_task->canAbort() : false; } + bool abort() override; protected: void setJavaPath(QString path); From 5232b3cd89ce70722865bc1ad6d96d8f52db1789 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 17 Feb 2024 12:17:00 +0200 Subject: [PATCH 043/120] Added some logs and fixed natives extraction Signed-off-by: Trial97 --- launcher/minecraft/MinecraftInstance.cpp | 11 ++++++----- launcher/minecraft/launch/AutoInstallJava.cpp | 5 ++++- launcher/minecraft/launch/VerifyJavaInstall.cpp | 11 +++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 00ce405aa..cfc65428c 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -1078,6 +1078,12 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(makeShared(pptr, Net::Mode::Offline)); } + // check java + { + process->appendStep(makeShared(pptr)); + process->appendStep(makeShared(pptr)); + } + // if there are any jar mods { process->appendStep(makeShared(pptr)); @@ -1102,11 +1108,6 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt { process->appendStep(makeShared(pptr)); } - // check java - { - process->appendStep(makeShared(pptr)); - process->appendStep(makeShared(pptr)); - } // verify that minimum Java requirements are met { diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index d93276432..7905689da 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -68,12 +68,15 @@ void AutoInstallJava::executeTask() } auto packProfile = m_instance->getPackProfile(); if (!APPLICATION->settings()->get("AutomaticJavaDownload").toBool()) { - auto javas = APPLICATION->javalist().get(); + auto javas = APPLICATION->javalist(); 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(javas->at(i)); if (java && packProfile->getProfile()->getCompatibleJavaMajors().contains(java->id.major())) { + if (!java->is_64bit) { + emit logLine(tr("The automatic Java mechanism detected a x32 java."), MessageLevel::Info); + } setJavaPath(java->path); return; } diff --git a/launcher/minecraft/launch/VerifyJavaInstall.cpp b/launcher/minecraft/launch/VerifyJavaInstall.cpp index 279545fed..536384f12 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.cpp +++ b/launcher/minecraft/launch/VerifyJavaInstall.cpp @@ -37,6 +37,7 @@ #include #include "Application.h" +#include "MessageLevel.h" #include "java/JavaInstall.h" #include "java/JavaInstallList.h" #include "java/JavaVersion.h" @@ -50,6 +51,16 @@ void VerifyJavaInstall::executeTask() 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(); + + emit logLine(tr("Java architecture is x%1.").arg(javaArchitecture), MessageLevel::Info); + if (javaArchitecture == "32" && maxMemAlloc > 2048) { + emit logLine(tr("Max memory allocation exceeds the supported value.\n" + "The selected java is 32 bit and doesn't support more than 2GB of ram.\n" + "The instance may not start due to this."), + MessageLevel::Error); + } auto compatibleMajors = packProfile->getProfile()->getCompatibleJavaMajors(); From a7dad96a701100ab583b4c9ca00a7c9b979fcf84 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Feb 2024 09:32:31 +0200 Subject: [PATCH 044/120] Added refresh button on managed java list Signed-off-by: Trial97 --- launcher/ui/pages/global/JavaPage.cpp | 4 ++++ launcher/ui/pages/global/JavaPage.h | 1 + launcher/ui/pages/global/JavaPage.ui | 7 +++++++ 3 files changed, 12 insertions(+) diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 496cb69a7..e967204c8 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -296,3 +296,7 @@ void JavaPage::on_removeJavaButton_clicked() } } } +void JavaPage::on_refreshJavaButton_clicked() +{ + ui->managedJavaList->loadList(); +} diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h index 03d14b824..1a521e2db 100644 --- a/launcher/ui/pages/global/JavaPage.h +++ b/launcher/ui/pages/global/JavaPage.h @@ -77,6 +77,7 @@ class JavaPage : public QWidget, public BasePage { void on_removeExtraPathButton_clicked(); void on_downloadJavaButton_clicked(); void on_removeJavaButton_clicked(); + void on_refreshJavaButton_clicked(); void on_maxMemSpinBox_valueChanged(int i); void checkerFinished(); diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index d135adc9a..80be81fb4 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -376,6 +376,13 @@ + + + + Refresh + + + From 4c76f7afe0a1ea015d7c0eac7a1a6b1c8a1a760a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Feb 2024 09:46:44 +0200 Subject: [PATCH 045/120] Made auto java checkbox dependent Signed-off-by: Trial97 --- launcher/ui/pages/global/JavaPage.cpp | 8 +++++++- launcher/ui/pages/global/JavaPage.ui | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index e967204c8..0e97211d9 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -41,6 +41,7 @@ #include "ui/java/JavaDownloader.h" #include "ui_JavaPage.h" +#include #include #include #include @@ -65,6 +66,11 @@ JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) ui->managedJavaList->selectCurrent(); ui->managedJavaList->setEmptyString(tr("No java versions are currently available in the meta")); ui->managedJavaList->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); + connect(ui->autodetectJavaCheckBox, &QCheckBox::stateChanged, this, [this] { + ui->autodownloadCheckBox->setEnabled(ui->autodetectJavaCheckBox->isChecked()); + if (!ui->autodetectJavaCheckBox->isChecked()) + ui->autodownloadCheckBox->setChecked(false); + }); loadSettings(); updateThresholds(); @@ -128,7 +134,7 @@ void JavaPage::loadSettings() ui->skipCompatibilityCheckbox->setChecked(s->get("IgnoreJavaCompatibility").toBool()); ui->skipJavaWizardCheckbox->setChecked(s->get("IgnoreJavaWizard").toBool()); ui->autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); - ui->autodownloadCheckBox->setChecked(s->get("AutomaticJavaDownload").toBool()); + ui->autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool()); m_extra_paths = new QStringListModel(s->get("JavaExtraSearchPaths").toStringList()); ui->extraJavaPathsList->setModel(m_extra_paths); } diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index 80be81fb4..43843017c 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -303,6 +303,9 @@ + + false + Autodownload Mojang Java From 2f489d1aec120274b3e98187bf8326c8990bca12 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Feb 2024 11:34:54 +0200 Subject: [PATCH 046/120] Added auto java options to the java wizzard page Signed-off-by: Trial97 --- launcher/ui/setupwizard/JavaWizardPage.cpp | 2 ++ launcher/ui/widgets/JavaSettingsWidget.cpp | 38 ++++++++++++++++++++++ launcher/ui/widgets/JavaSettingsWidget.h | 8 +++++ 3 files changed, 48 insertions(+) diff --git a/launcher/ui/setupwizard/JavaWizardPage.cpp b/launcher/ui/setupwizard/JavaWizardPage.cpp index abe4860da..d537580fc 100644 --- a/launcher/ui/setupwizard/JavaWizardPage.cpp +++ b/launcher/ui/setupwizard/JavaWizardPage.cpp @@ -57,6 +57,8 @@ bool JavaWizardPage::validatePage() { auto settings = APPLICATION->settings(); auto result = m_java_widget->validate(); + settings->set("AutomaticJavaSwitch", m_java_widget->autodetectJava()); + settings->set("AutomaticJavaDownload", m_java_widget->autodownloadJava()); switch (result) { default: case JavaSettingsWidget::ValidationStatus::Bad: { diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 507c632d5..c15f7bf42 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -136,6 +136,26 @@ void JavaSettingsWidget::setupUi() m_verticalLayout->addLayout(m_horizontalBtnLayout); + m_autoJavaGroupBox = new QGroupBox(this); + m_autoJavaGroupBox->setObjectName(QStringLiteral("autoJavaGroupBox")); + m_veriticalJavaLayout = new QVBoxLayout(m_autoJavaGroupBox); + m_veriticalJavaLayout->setObjectName(QStringLiteral("veriticalJavaLayout")); + + m_autodetectJavaCheckBox = new QCheckBox(m_autoJavaGroupBox); + m_autodetectJavaCheckBox->setObjectName("autodetectJavaCheckBox"); + m_veriticalJavaLayout->addWidget(m_autodetectJavaCheckBox); + + m_autodownloadCheckBox = new QCheckBox(m_autoJavaGroupBox); + m_autodownloadCheckBox->setObjectName("autodownloadCheckBox"); + m_autodownloadCheckBox->setEnabled(false); + m_veriticalJavaLayout->addWidget(m_autodownloadCheckBox); + connect(m_autodetectJavaCheckBox, &QCheckBox::stateChanged, this, [this] { + m_autodownloadCheckBox->setEnabled(m_autodetectJavaCheckBox->isChecked()); + if (!m_autodetectJavaCheckBox->isChecked()) + m_autodownloadCheckBox->setChecked(false); + }); + m_verticalLayout->addWidget(m_autoJavaGroupBox); + retranslate(); } @@ -153,6 +173,9 @@ void JavaSettingsWidget::initialize() m_maxMemSpinBox->setValue(observedMaxMemory); m_permGenSpinBox->setValue(observedPermGenMemory); updateThresholds(); + + m_autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); + m_autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool()); } void JavaSettingsWidget::refresh() @@ -280,11 +303,13 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked() m_javaPathTextBox->setText(cooked_path); checkJavaPath(cooked_path); } + void JavaSettingsWidget::on_javaDownloadBtn_clicked() { auto jdialog = new Java::Downloader(this); jdialog->exec(); } + void JavaSettingsWidget::on_javaStatusBtn_clicked() { QString text; @@ -418,6 +443,9 @@ void JavaSettingsWidget::retranslate() m_minMemSpinBox->setToolTip(tr("The amount of memory Minecraft is started with.")); m_permGenSpinBox->setToolTip(tr("The amount of memory available to store loaded Java classes.")); m_javaBrowseBtn->setText(tr("Browse")); + m_autodownloadCheckBox->setText(tr("Autodownload Mojang Java")); + m_autodetectJavaCheckBox->setText(tr("Autodetect Java version")); + m_autoJavaGroupBox->setTitle(tr("Autodetect Java")); } void JavaSettingsWidget::updateThresholds() @@ -464,3 +492,13 @@ void JavaSettingsWidget::on_addJavaPathBtn_clicked() APPLICATION->settings()->set("JavaExtraSearchPaths", currentList); refresh(); } + +bool JavaSettingsWidget::autodownloadJava() const +{ + return m_autodetectJavaCheckBox->isChecked(); +} + +bool JavaSettingsWidget::autodetectJava() const +{ + return m_autodownloadCheckBox->isChecked(); +} diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index 385a9256a..205b83d8c 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -4,6 +4,7 @@ #include #include #include +#include #include class QLineEdit; @@ -41,6 +42,8 @@ class JavaSettingsWidget : public QWidget { int minHeapSize() const; int maxHeapSize() const; QString javaPath() const; + bool autodetectJava() const; + bool autodownloadJava() const; void updateThresholds(); @@ -86,6 +89,11 @@ class JavaSettingsWidget : public QWidget { QIcon yellowIcon; QIcon badIcon; + QGroupBox* m_autoJavaGroupBox = nullptr; + QVBoxLayout* m_veriticalJavaLayout = nullptr; + QCheckBox* m_autodetectJavaCheckBox = nullptr; + QCheckBox* m_autodownloadCheckBox = nullptr; + unsigned int observedMinMemory = 0; unsigned int observedMaxMemory = 0; unsigned int observedPermGenMemory = 0; From 4aafa98852ec1f89cc765def26ab9e4174b8af3b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Feb 2024 12:58:34 +0200 Subject: [PATCH 047/120] Improved the message boxes for java wizzard Signed-off-by: Trial97 --- launcher/ui/widgets/JavaSettingsWidget.cpp | 71 ++++++++++++++++++---- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index c15f7bf42..66278abb0 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -11,6 +12,7 @@ #include +#include "DesktopServices.h" #include "FileSystem.h" #include "JavaCommon.h" #include "java/JavaChecker.h" @@ -174,8 +176,19 @@ void JavaSettingsWidget::initialize() m_permGenSpinBox->setValue(observedPermGenMemory); updateThresholds(); - m_autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); - m_autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool()); + auto button = CustomMessageBox::selectable(this, tr("Auto Java Download"), + tr("%1 has now the ability to auto downloand the correct java for each minecraft version.\n" + "Do you want to enable java auto-download?\n") + .arg(BuildConfig.LAUNCHER_DISPLAYNAME), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) + ->exec(); + if (button == QMessageBox::Yes) { + m_autodetectJavaCheckBox->setChecked(true); + m_autodownloadCheckBox->setChecked(true); + } else { + m_autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); + m_autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool()); + } } void JavaSettingsWidget::refresh() @@ -192,20 +205,52 @@ JavaSettingsWidget::ValidationStatus JavaSettingsWidget::validate() switch (javaStatus) { default: case JavaStatus::NotSet: + /* fallthrough */ case JavaStatus::DoesNotExist: + /* fallthrough */ case JavaStatus::DoesNotStart: + /* fallthrough */ case JavaStatus::ReturnedInvalidData: { - int button = CustomMessageBox::selectable(this, tr("No Java version selected"), - tr("You didn't select a Java version or selected something that doesn't work.\n" - "%1 will not be able to start Minecraft.\n" - "Do you wish to proceed without any Java?" - "\n\n" - "You can change the Java version in the settings later.\n") - .arg(BuildConfig.LAUNCHER_DISPLAYNAME), - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton) - ->exec(); - if (button == QMessageBox::No) { - return ValidationStatus::Bad; + if (!m_autodownloadCheckBox->isChecked()) { // the java will not be autodownloaded + int button = QMessageBox::No; + if (m_result.mojangPlatform == "32" && maxHeapSize() > 2048) { + button = CustomMessageBox::selectable( + this, tr("Java x32 detected"), + tr("You selected a 32 bit java, but allocated more than 2048MiB as maximum memory.\n" + "%1 will not be able to start Minecraft.\n" + "Do you wish to proceed?" + "\n\n" + "You can change the Java version in the settings later.\n") + .arg(BuildConfig.LAUNCHER_DISPLAYNAME), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No | QMessageBox::Help, QMessageBox::NoButton) + ->exec(); + + } else { + button = CustomMessageBox::selectable(this, tr("No Java version selected"), + tr("You didn't select a Java version or selected something that doesn't work.\n" + "%1 will not be able to start Minecraft.\n" + "Do you wish to proceed without any Java?" + "\n\n" + "You can change the Java version in the settings later.\n") + .arg(BuildConfig.LAUNCHER_DISPLAYNAME), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No | QMessageBox::Help, + QMessageBox::NoButton) + ->exec(); + } + switch (button) { + case QMessageBox::Yes: + return ValidationStatus::JavaBad; + case QMessageBox::Help: + DesktopServices::openUrl(QUrl(BuildConfig.HELP_URL.arg("java-wizzard"))); + /* fallthrough */ + case QMessageBox::No: + /* fallthrough */ + default: + return ValidationStatus::Bad; + } + if (button == QMessageBox::No) { + return ValidationStatus::Bad; + } } return ValidationStatus::JavaBad; } break; From b4f3a969b3fd2f96675d25e3c8726c76395b3d7e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Feb 2024 14:30:38 +0200 Subject: [PATCH 048/120] Updated strings that are displayed to user Signed-off-by: Trial97 --- launcher/MMCZip.cpp | 2 +- launcher/MMCZip.h | 2 +- launcher/java/JavaInstall.cpp | 2 +- launcher/java/JavaInstall.h | 2 +- launcher/java/JavaMetadata.cpp | 2 +- launcher/java/JavaMetadata.h | 2 +- launcher/java/download/ArchiveDownloadTask.cpp | 2 +- launcher/java/download/ArchiveDownloadTask.h | 2 +- launcher/java/download/ManifestDownloadTask.cpp | 2 +- launcher/java/download/ManifestDownloadTask.h | 2 +- launcher/minecraft/launch/AutoInstallJava.cpp | 10 +++++----- launcher/minecraft/launch/AutoInstallJava.h | 2 +- launcher/minecraft/launch/VerifyJavaInstall.cpp | 2 +- launcher/ui/java/JavaDownloader.cpp | 2 +- launcher/ui/pages/global/JavaPage.cpp | 2 +- launcher/ui/pages/global/JavaPage.ui | 2 +- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 2 +- launcher/ui/pages/instance/InstanceSettingsPage.ui | 3 --- launcher/ui/widgets/JavaSettingsWidget.cpp | 6 +++--- 19 files changed, 24 insertions(+), 27 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 9e26c5eda..8273acbb6 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index db6a7421a..e2987badd 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/java/JavaInstall.cpp b/launcher/java/JavaInstall.cpp index cfa471402..8e97e0e14 100644 --- a/launcher/java/JavaInstall.cpp +++ b/launcher/java/JavaInstall.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/java/JavaInstall.h b/launcher/java/JavaInstall.h index 6890264f3..7d8d392fa 100644 --- a/launcher/java/JavaInstall.h +++ b/launcher/java/JavaInstall.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/java/JavaMetadata.cpp b/launcher/java/JavaMetadata.cpp index b261122dc..b73c54fe6 100644 --- a/launcher/java/JavaMetadata.cpp +++ b/launcher/java/JavaMetadata.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/java/JavaMetadata.h b/launcher/java/JavaMetadata.h index dd3ae865c..640a412f1 100644 --- a/launcher/java/JavaMetadata.h +++ b/launcher/java/JavaMetadata.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/java/download/ArchiveDownloadTask.cpp b/launcher/java/download/ArchiveDownloadTask.cpp index 9f8dc0543..e3db77d2c 100644 --- a/launcher/java/download/ArchiveDownloadTask.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/java/download/ArchiveDownloadTask.h b/launcher/java/download/ArchiveDownloadTask.h index 88c0223d5..c656567fe 100644 --- a/launcher/java/download/ArchiveDownloadTask.h +++ b/launcher/java/download/ArchiveDownloadTask.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/java/download/ManifestDownloadTask.cpp b/launcher/java/download/ManifestDownloadTask.cpp index 0c2eee0c8..ba5ff2cc0 100644 --- a/launcher/java/download/ManifestDownloadTask.cpp +++ b/launcher/java/download/ManifestDownloadTask.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/java/download/ManifestDownloadTask.h b/launcher/java/download/ManifestDownloadTask.h index dcfee4d4d..f0eaf95a6 100644 --- a/launcher/java/download/ManifestDownloadTask.h +++ b/launcher/java/download/ManifestDownloadTask.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index 7905689da..ab68910a7 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -75,13 +75,13 @@ void AutoInstallJava::executeTask() auto java = std::dynamic_pointer_cast(javas->at(i)); if (java && packProfile->getProfile()->getCompatibleJavaMajors().contains(java->id.major())) { if (!java->is_64bit) { - emit logLine(tr("The automatic Java mechanism detected a x32 java."), MessageLevel::Info); + emit logLine(tr("The automatic Java mechanism detected an x32 java."), MessageLevel::Info); } setJavaPath(java->path); return; } } - emit logLine(tr("No comptatible java version was found. Using the default one."), MessageLevel::Warning); + 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); @@ -136,7 +136,7 @@ void AutoInstallJava::setJavaPathFromPartial() if (QFileInfo::exists(finalPath)) { setJavaPath(finalPath); } else { - emit logLine(tr("No comptatible java version was found. Using the default one."), MessageLevel::Warning); + emit logLine(tr("No compatible java version was found. Using the default one."), MessageLevel::Warning); emitSucceeded(); } return; @@ -192,7 +192,7 @@ void AutoInstallJava::tryNextMajorJava() auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName(); auto majorJavaVersions = packProfile->getProfile()->getCompatibleJavaMajors(); if (m_majorJavaVersionIndex >= majorJavaVersions.length()) { - emit logLine(tr("No comptatible java version was found. Using the default one."), MessageLevel::Warning); + emit logLine(tr("No compatible java version was found. Using the default one."), MessageLevel::Warning); emitSucceeded(); return; } diff --git a/launcher/minecraft/launch/AutoInstallJava.h b/launcher/minecraft/launch/AutoInstallJava.h index 45d0f870e..7e4efc50c 100644 --- a/launcher/minecraft/launch/AutoInstallJava.h +++ b/launcher/minecraft/launch/AutoInstallJava.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (c) 2023-2024 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/minecraft/launch/VerifyJavaInstall.cpp b/launcher/minecraft/launch/VerifyJavaInstall.cpp index 536384f12..f26b850eb 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.cpp +++ b/launcher/minecraft/launch/VerifyJavaInstall.cpp @@ -57,7 +57,7 @@ void VerifyJavaInstall::executeTask() emit logLine(tr("Java architecture is x%1.").arg(javaArchitecture), MessageLevel::Info); if (javaArchitecture == "32" && maxMemAlloc > 2048) { emit logLine(tr("Max memory allocation exceeds the supported value.\n" - "The selected java is 32 bit and doesn't support more than 2GB of ram.\n" + "The selected java is 32-bit and doesn't support more than 2048MiB of RAM.\n" "The instance may not start due to this."), MessageLevel::Error); } diff --git a/launcher/ui/java/JavaDownloader.cpp b/launcher/ui/java/JavaDownloader.cpp index 4495210c3..7417a4ea8 100644 --- a/launcher/ui/java/JavaDownloader.cpp +++ b/launcher/ui/java/JavaDownloader.cpp @@ -49,7 +49,7 @@ Downloader::Downloader(QWidget* parent) : QDialog(parent), ui(new Ui::JavaDownlo versionList->setProvidedRoles({ BaseVersionList::VersionRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole }); ui->majorVersionSelect->initialize(versionList.get()); ui->majorVersionSelect->selectCurrent(); - ui->majorVersionSelect->setEmptyString(tr("No java versions are currently available in the meta")); + ui->majorVersionSelect->setEmptyString(tr("No java versions are currently available in the meta.")); ui->majorVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); ui->javaVersionSelect->setEmptyString(tr("No java versions are currently available for your OS.")); diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 0e97211d9..524165e62 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -158,7 +158,7 @@ void JavaPage::on_javaDetectBtn_clicked() if (!java->is_64bit && APPLICATION->settings()->get("MaxMemAlloc").toInt() > 2048) { CustomMessageBox::selectable(this, tr("Confirm Selection"), tr("You selected an x86 java version.\n" - "This means that will not support more than 2Gb(2048Mb) of ram.\n" + "This means that will not support more than 2048MiB of RAM.\n" "Please make sure that the maximum memory value is lower."), QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok) ->exec(); diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index 43843017c..3f763f8d2 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -307,7 +307,7 @@ false - Autodownload Mojang Java + Auto-download Mojang Java diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 926e48952..8a63aab22 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -417,7 +417,7 @@ void InstanceSettingsPage::on_javaDetectBtn_clicked() if (!java->is_64bit && m_settings->get("MaxMemAlloc").toInt() > 2048) { CustomMessageBox::selectable(this, tr("Confirm Selection"), tr("You selected an x86 java version.\n" - "This means that will not support more than 2Gb(2048Mb) of ram.\n" + "This means that will not support more than 2048MiB of RAM.\n" "Please make sure that the maximum memory value is lower."), QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok) ->exec(); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 7762ca8a7..94464064e 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -617,9 +617,6 @@ Enable online fixes (experimental) - - Disable Quilt Loader Beacon - diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 66278abb0..91fd6ff03 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -216,7 +216,7 @@ JavaSettingsWidget::ValidationStatus JavaSettingsWidget::validate() if (m_result.mojangPlatform == "32" && maxHeapSize() > 2048) { button = CustomMessageBox::selectable( this, tr("Java x32 detected"), - tr("You selected a 32 bit java, but allocated more than 2048MiB as maximum memory.\n" + tr("You selected an 32-bit java, but allocated more than 2048MiB as maximum memory.\n" "%1 will not be able to start Minecraft.\n" "Do you wish to proceed?" "\n\n" @@ -488,7 +488,7 @@ void JavaSettingsWidget::retranslate() m_minMemSpinBox->setToolTip(tr("The amount of memory Minecraft is started with.")); m_permGenSpinBox->setToolTip(tr("The amount of memory available to store loaded Java classes.")); m_javaBrowseBtn->setText(tr("Browse")); - m_autodownloadCheckBox->setText(tr("Autodownload Mojang Java")); + m_autodownloadCheckBox->setText(tr("Auto-download Mojang Java")); m_autodetectJavaCheckBox->setText(tr("Autodetect Java version")); m_autoJavaGroupBox->setTitle(tr("Autodetect Java")); } @@ -509,7 +509,7 @@ void JavaSettingsWidget::updateThresholds() } else if (observedMaxMemory > 2048 && m_result.is_64bit) { iconName = "status-bad"; m_labelMaxMemIcon->setToolTip( - tr("Your maximum memory allocation exceeds selected java posible memory(due to x86 applicatiion limitations).")); + tr("Your maximum memory allocation exceeds selected java possible memory(due to x86 application limitations).")); } else { iconName = "status-good"; m_labelMaxMemIcon->setToolTip(""); From 038d3e4596586718ca6982c68a17c36723561a42 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Feb 2024 16:49:10 +0200 Subject: [PATCH 049/120] Fixed asan complains Signed-off-by: Trial97 --- launcher/java/download/ArchiveDownloadTask.cpp | 5 ++++- launcher/java/download/ManifestDownloadTask.cpp | 5 ++++- launcher/ui/pages/global/JavaPage.cpp | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/launcher/java/download/ArchiveDownloadTask.cpp b/launcher/java/download/ArchiveDownloadTask.cpp index e3db77d2c..34f60260e 100644 --- a/launcher/java/download/ArchiveDownloadTask.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -49,7 +49,10 @@ void ArchiveDownloadTask::executeTask() download->addNetAction(action); auto fullPath = entry->getFullPath(); - connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); + connect(download.get(), &NetJob::finished, [download, this] { + disconnect(this, &Task::aborted, download.get(), &NetJob::abort); + download->deleteLater(); + }); connect(download.get(), &NetJob::failed, this, &ArchiveDownloadTask::emitFailed); connect(this, &Task::aborted, download.get(), &NetJob::abort); connect(download.get(), &Task::progress, this, &ArchiveDownloadTask::setProgress); diff --git a/launcher/java/download/ManifestDownloadTask.cpp b/launcher/java/download/ManifestDownloadTask.cpp index ba5ff2cc0..5551c75d5 100644 --- a/launcher/java/download/ManifestDownloadTask.cpp +++ b/launcher/java/download/ManifestDownloadTask.cpp @@ -51,7 +51,10 @@ void ManifestDownloadTask::executeTask() } download->addNetAction(action); - connect(download.get(), &NetJob::finished, [download, this] { disconnect(this, &Task::aborted, download.get(), &NetJob::abort); }); + connect(download.get(), &NetJob::finished, [download, this] { + disconnect(this, &Task::aborted, download.get(), &NetJob::abort); + download->deleteLater(); + }); connect(download.get(), &NetJob::failed, this, &ManifestDownloadTask::emitFailed); connect(this, &Task::aborted, download.get(), &NetJob::abort); connect(download.get(), &Task::progress, this, &ManifestDownloadTask::setProgress); diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 524165e62..deb085f93 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -135,7 +135,7 @@ void JavaPage::loadSettings() ui->skipJavaWizardCheckbox->setChecked(s->get("IgnoreJavaWizard").toBool()); ui->autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); ui->autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool()); - m_extra_paths = new QStringListModel(s->get("JavaExtraSearchPaths").toStringList()); + m_extra_paths = new QStringListModel(s->get("JavaExtraSearchPaths").toStringList(), this); ui->extraJavaPathsList->setModel(m_extra_paths); } @@ -199,6 +199,7 @@ void JavaPage::on_javaDownloadBtn_clicked() { auto jdialog = new Java::Downloader(this); jdialog->exec(); + ui->managedJavaList->loadList(); } void JavaPage::on_maxMemSpinBox_valueChanged([[maybe_unused]] int i) From 889f604a415fd01150868090a1d47b7c408104d5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Feb 2024 21:38:31 +0200 Subject: [PATCH 050/120] Removed JavaExtraSearchPaths Signed-off-by: Trial97 --- launcher/Application.cpp | 1 - launcher/java/JavaUtils.cpp | 37 ------------------- launcher/java/JavaUtils.h | 1 - launcher/ui/pages/global/JavaPage.cpp | 27 -------------- launcher/ui/pages/global/JavaPage.h | 3 -- launcher/ui/pages/global/JavaPage.ui | 43 ---------------------- launcher/ui/widgets/JavaSettingsWidget.cpp | 19 ---------- launcher/ui/widgets/JavaSettingsWidget.h | 2 - 8 files changed, 133 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 6b7333972..31950a813 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -632,7 +632,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("JvmArgs", ""); m_settings->registerSetting("IgnoreJavaCompatibility", false); m_settings->registerSetting("IgnoreJavaWizard", false); - m_settings->registerSetting("JavaExtraSearchPaths", QStringList()); m_settings->registerSetting("AutomaticJavaSwitch", false); m_settings->registerSetting("AutomaticJavaDownload", false); diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 1d254e405..57e381e1d 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -338,7 +338,6 @@ QList JavaUtils::FindJavaPaths() candidates.append(getMinecraftJavaBundle()); candidates.append(getPrismJavaBundle()); - candidates.append(getPrismExtraJavaPaths()); candidates = addJavasFromEnv(candidates); candidates.removeDuplicates(); return candidates; @@ -366,7 +365,6 @@ QList JavaUtils::FindJavaPaths() } javas.append(getMinecraftJavaBundle()); javas.append(getPrismJavaBundle()); - javas.append(getPrismExtraJavaPaths()); javas = addJavasFromEnv(javas); javas.removeDuplicates(); return javas; @@ -420,7 +418,6 @@ QList JavaUtils::FindJavaPaths() javas.append(getMinecraftJavaBundle()); javas.append(getPrismJavaBundle()); - javas.append(getPrismExtraJavaPaths()); javas = addJavasFromEnv(javas); javas.removeDuplicates(); return javas; @@ -435,7 +432,6 @@ QList JavaUtils::FindJavaPaths() javas.append(getMinecraftJavaBundle()); javas.append(getPrismJavaBundle()); - javas.append(getPrismExtraJavaPaths()); javas.removeDuplicates(); return addJavasFromEnv(javas); } @@ -521,36 +517,3 @@ QStringList getPrismJavaBundle() return javas; } - -QStringList getPrismExtraJavaPaths() -{ - QList javas; - - QString executable = "java"; -#if defined(Q_OS_WIN32) - executable += "w.exe"; -#endif - - auto scanDir = [&](QString prefix) { - javas.append(FS::PathCombine(prefix, "jre", "bin", executable)); - javas.append(FS::PathCombine(prefix, "bin", executable)); - javas.append(FS::PathCombine(prefix, executable)); - }; - auto scanJavaDir = [&](const QString& dirPath) { - QDir dir(dirPath); - if (!dir.exists()) - return; - auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); - for (auto& entry : entries) { - scanDir(entry.canonicalFilePath()); - } - }; - - auto extra_paths = APPLICATION->settings()->get("JavaExtraSearchPaths").toStringList(); - for (auto& entry : extra_paths) { - scanDir(entry); - scanJavaDir(entry); - } - - return javas; -} diff --git a/launcher/java/JavaUtils.h b/launcher/java/JavaUtils.h index 66e439834..aa5315a19 100644 --- a/launcher/java/JavaUtils.h +++ b/launcher/java/JavaUtils.h @@ -27,7 +27,6 @@ QString stripVariableEntries(QString name, QString target, QString remove); QProcessEnvironment CleanEnviroment(); QStringList getMinecraftJavaBundle(); QStringList getPrismJavaBundle(); -QStringList getPrismExtraJavaPaths(); class JavaUtils : public QObject { Q_OBJECT diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index deb085f93..cb2a8b90b 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -110,7 +110,6 @@ void JavaPage::applySettings() s->set("IgnoreJavaWizard", ui->skipJavaWizardCheckbox->isChecked()); s->set("AutomaticJavaSwitch", ui->autodetectJavaCheckBox->isChecked()); s->set("AutomaticJavaDownload", ui->autodownloadCheckBox->isChecked()); - s->set("JavaExtraSearchPaths", m_extra_paths->stringList()); JavaCommon::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget()); } void JavaPage::loadSettings() @@ -135,8 +134,6 @@ void JavaPage::loadSettings() ui->skipJavaWizardCheckbox->setChecked(s->get("IgnoreJavaWizard").toBool()); ui->autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); ui->autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool()); - m_extra_paths = new QStringListModel(s->get("JavaExtraSearchPaths").toStringList(), this); - ui->extraJavaPathsList->setModel(m_extra_paths); } void JavaPage::on_javaDetectBtn_clicked() @@ -247,30 +244,6 @@ void JavaPage::updateThresholds() } } -void JavaPage::on_addExtraPathButton_clicked() -{ - QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Add Extra Java Folder")); - - if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { - QString cooked_dir = FS::NormalizePath(raw_dir); - auto currentList = m_extra_paths->stringList(); - if (!currentList.contains(cooked_dir)) { - currentList << cooked_dir; - m_extra_paths->setStringList(currentList); - } - } - APPLICATION->settings()->set("JavaExtraSearchPaths", m_extra_paths->stringList()); -} - -void JavaPage::on_removeExtraPathButton_clicked() -{ - auto indexes = ui->extraJavaPathsList->selectionModel()->selectedIndexes(); - if (indexes.size()) { - m_extra_paths->removeRow(indexes.first().row()); - } - APPLICATION->settings()->set("JavaExtraSearchPaths", m_extra_paths->stringList()); -} - void JavaPage::on_downloadJavaButton_clicked() { on_javaDownloadBtn_clicked(); diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h index 1a521e2db..48e557740 100644 --- a/launcher/ui/pages/global/JavaPage.h +++ b/launcher/ui/pages/global/JavaPage.h @@ -73,8 +73,6 @@ class JavaPage : public QWidget, public BasePage { void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); void on_javaDownloadBtn_clicked(); - void on_addExtraPathButton_clicked(); - void on_removeExtraPathButton_clicked(); void on_downloadJavaButton_clicked(); void on_removeJavaButton_clicked(); void on_refreshJavaButton_clicked(); @@ -84,5 +82,4 @@ class JavaPage : public QWidget, public BasePage { private: Ui::JavaPage* ui; unique_qobject_ptr checker; - QStringListModel* m_extra_paths; }; diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index 3f763f8d2..dc1668ee3 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -391,49 +391,6 @@ - - - - Java extra paths - - - - - - - - - - - Add - - - - - - - Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 91fd6ff03..4b5819288 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -44,7 +44,6 @@ JavaSettingsWidget::JavaSettingsWidget(QWidget* parent) : QWidget(parent) connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaSettingsWidget::javaPathEdited); connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaSettingsWidget::on_javaStatusBtn_clicked); connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaDownloadBtn_clicked); - connect(m_addJavaPathBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_addJavaPathBtn_clicked); } void JavaSettingsWidget::setupUi() @@ -133,9 +132,6 @@ void JavaSettingsWidget::setupUi() m_javaDownloadBtn = new QPushButton(tr("Download Java"), this); m_horizontalBtnLayout->addWidget(m_javaDownloadBtn); - m_addJavaPathBtn = new QPushButton(tr("Add extra Java path"), this); - m_horizontalBtnLayout->addWidget(m_addJavaPathBtn); - m_verticalLayout->addLayout(m_horizontalBtnLayout); m_autoJavaGroupBox = new QGroupBox(this); @@ -523,21 +519,6 @@ void JavaSettingsWidget::updateThresholds() } } -void JavaSettingsWidget::on_addJavaPathBtn_clicked() -{ - QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Add Extra Java Folder")); - - auto currentList = APPLICATION->settings()->get("JavaExtraSearchPaths").toStringList(); - if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { - QString cooked_dir = FS::NormalizePath(raw_dir); - if (!currentList.contains(cooked_dir)) { - currentList << cooked_dir; - } - } - APPLICATION->settings()->set("JavaExtraSearchPaths", currentList); - refresh(); -} - bool JavaSettingsWidget::autodownloadJava() const { return m_autodetectJavaCheckBox->isChecked(); diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index 205b83d8c..c8b6953df 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -54,7 +54,6 @@ class JavaSettingsWidget : public QWidget { void on_javaBrowseBtn_clicked(); void on_javaStatusBtn_clicked(); void on_javaDownloadBtn_clicked(); - void on_addJavaPathBtn_clicked(); void checkFinished(const JavaChecker::Result& result); protected: /* methods */ @@ -84,7 +83,6 @@ class JavaSettingsWidget : public QWidget { QHBoxLayout* m_horizontalBtnLayout = nullptr; QPushButton* m_javaDownloadBtn = nullptr; - QPushButton* m_addJavaPathBtn = nullptr; QIcon goodIcon; QIcon yellowIcon; QIcon badIcon; From 1c96ae58077cae7a8d5b8f851d5ede385811f6ea Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Feb 2024 22:32:54 +0200 Subject: [PATCH 051/120] Fixed java refresh button Signed-off-by: Trial97 --- launcher/ui/java/JavaDownloader.cpp | 3 ++- launcher/ui/java/JavaDownloader.ui | 10 +++++----- launcher/ui/java/VersionList.cpp | 4 +++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/launcher/ui/java/JavaDownloader.cpp b/launcher/ui/java/JavaDownloader.cpp index 7417a4ea8..24918dd76 100644 --- a/launcher/ui/java/JavaDownloader.cpp +++ b/launcher/ui/java/JavaDownloader.cpp @@ -55,7 +55,7 @@ Downloader::Downloader(QWidget* parent) : QDialog(parent), ui(new Ui::JavaDownlo ui->javaVersionSelect->setEmptyString(tr("No java versions are currently available for your OS.")); ui->javaVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); - ui->buttonBox->button(QDialogButtonBox::Retry)->setText(tr("Refresh")); + ui->buttonBox->button(QDialogButtonBox::Reset)->setText(tr("Refresh")); ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Download")); connect(ui->majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &Downloader::setSelectedVersion); @@ -98,6 +98,7 @@ void Downloader::accept() connect(task.get(), &Task::failed, this, deletePath); connect(task.get(), &Task::aborted, this, deletePath); ProgressDialog pg(this); + pg.setSkipButton(true, tr("Abort")); pg.execWithTask(task.get()); QDialog::accept(); } diff --git a/launcher/ui/java/JavaDownloader.ui b/launcher/ui/java/JavaDownloader.ui index 0eeabb26d..3f6a8adc6 100644 --- a/launcher/ui/java/JavaDownloader.ui +++ b/launcher/ui/java/JavaDownloader.ui @@ -48,7 +48,7 @@ Qt::Horizontal - QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Retry + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset @@ -71,8 +71,8 @@ accept() - 248 - 254 + 257 + 583 157 @@ -87,8 +87,8 @@ reject() - 316 - 260 + 325 + 583 286 diff --git a/launcher/ui/java/VersionList.cpp b/launcher/ui/java/VersionList.cpp index 7c5668d20..4bf04224a 100644 --- a/launcher/ui/java/VersionList.cpp +++ b/launcher/ui/java/VersionList.cpp @@ -104,10 +104,12 @@ bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right) void VersionList::sortVersions() { + if (!m_version || !m_version->data()) + return; QString versionStr = SysInfo::getSupportedJavaArchitecture(); beginResetModel(); auto runtimes = m_version->data()->runtimes; - if (!versionStr.isEmpty() && runtimes.contains(versionStr)) { + if (!versionStr.isEmpty() && !runtimes.isEmpty() && runtimes.contains(versionStr)) { m_vlist = runtimes.value(versionStr); std::sort(m_vlist.begin(), m_vlist.end(), sortJavas); } else { From da96172b0b8835df8591368e96d20464a3a4eb41 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Mon, 26 Feb 2024 22:00:40 +0200 Subject: [PATCH 052/120] Apply suggestions from code review Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/java/VersionList.cpp | 2 +- launcher/ui/pages/global/JavaPage.cpp | 2 +- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 2 +- launcher/ui/widgets/JavaSettingsWidget.cpp | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/launcher/ui/java/VersionList.cpp b/launcher/ui/java/VersionList.cpp index 4bf04224a..dc454f264 100644 --- a/launcher/ui/java/VersionList.cpp +++ b/launcher/ui/java/VersionList.cpp @@ -114,7 +114,7 @@ void VersionList::sortVersions() std::sort(m_vlist.begin(), m_vlist.end(), sortJavas); } else { m_vlist = {}; - qWarning() << "Your operating system is not yet supported: " << SysInfo::currentSystem() << " " << SysInfo::useQTForArch(); + qWarning() << "No Java versions found for your operating system." << SysInfo::currentSystem() << " " << SysInfo::useQTForArch(); } endResetModel(); } diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index cb2a8b90b..95d5f581e 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -154,7 +154,7 @@ void JavaPage::on_javaDetectBtn_clicked() ui->javaPathTextBox->setText(java->path); if (!java->is_64bit && APPLICATION->settings()->get("MaxMemAlloc").toInt() > 2048) { CustomMessageBox::selectable(this, tr("Confirm Selection"), - tr("You selected an x86 java version.\n" + tr("You selected a 32 bit java version.\n" "This means that will not support more than 2048MiB of RAM.\n" "Please make sure that the maximum memory value is lower."), QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 8a63aab22..50cffc9a7 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -416,7 +416,7 @@ void InstanceSettingsPage::on_javaDetectBtn_clicked() if (!java->is_64bit && m_settings->get("MaxMemAlloc").toInt() > 2048) { CustomMessageBox::selectable(this, tr("Confirm Selection"), - tr("You selected an x86 java version.\n" + tr("You selected a 32 bit java version.\n" "This means that will not support more than 2048MiB of RAM.\n" "Please make sure that the maximum memory value is lower."), QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 4b5819288..f8031687b 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -173,8 +173,8 @@ void JavaSettingsWidget::initialize() updateThresholds(); auto button = CustomMessageBox::selectable(this, tr("Auto Java Download"), - tr("%1 has now the ability to auto downloand the correct java for each minecraft version.\n" - "Do you want to enable java auto-download?\n") + tr("%1 can automatically download the correct Java version for each version of Minecraft..\n" + "Do you want to enable Java auto-download?\n") .arg(BuildConfig.LAUNCHER_DISPLAYNAME), QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) ->exec(); @@ -505,7 +505,7 @@ void JavaSettingsWidget::updateThresholds() } else if (observedMaxMemory > 2048 && m_result.is_64bit) { iconName = "status-bad"; m_labelMaxMemIcon->setToolTip( - tr("Your maximum memory allocation exceeds selected java possible memory(due to x86 application limitations).")); + tr("Because you're using 32 bit Java, you're exceeding the maximum possible allocation.")); } else { iconName = "status-good"; m_labelMaxMemIcon->setToolTip(""); From 24fd07861b797fb845217c04b9ad5267edcc4470 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 26 Feb 2024 22:25:14 +0200 Subject: [PATCH 053/120] format code Signed-off-by: Trial97 --- launcher/ui/widgets/JavaSettingsWidget.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index f8031687b..29357bdab 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -504,8 +504,7 @@ void JavaSettingsWidget::updateThresholds() m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value")); } else if (observedMaxMemory > 2048 && m_result.is_64bit) { iconName = "status-bad"; - m_labelMaxMemIcon->setToolTip( - tr("Because you're using 32 bit Java, you're exceeding the maximum possible allocation.")); + m_labelMaxMemIcon->setToolTip(tr("Because you're using 32 bit Java, you're exceeding the maximum possible allocation.")); } else { iconName = "status-good"; m_labelMaxMemIcon->setToolTip(""); From 9120848278f8709525b574e92a4e602c593e1f4c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 6 Mar 2024 19:33:14 +0200 Subject: [PATCH 054/120] Made java downloader as a build option Signed-off-by: Trial97 --- CMakeLists.txt | 3 +++ buildconfig/BuildConfig.cpp.in | 4 +++ buildconfig/BuildConfig.h | 1 + launcher/CMakeLists.txt | 4 +++ launcher/ui/pages/global/JavaPage.cpp | 25 +++++++++++------- .../pages/instance/InstanceSettingsPage.cpp | 2 ++ launcher/ui/widgets/JavaSettingsWidget.cpp | 26 +++++++++++-------- 7 files changed, 45 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cceb2599..9b7104478 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,6 +219,9 @@ set(Launcher_SUBREDDIT_URL "https://prismlauncher.org/reddit" CACHE STRING "URL set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules") set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build against") +# Java downloader +option(ENABLE_JAVA_DOWNLOADER "Build the java downloader feature" ON) + # Native libraries if(UNIX AND APPLE) set(Launcher_GLFW_LIBRARY_NAME "libglfw.dylib" CACHE STRING "Name of native glfw library") diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index b40cacb0f..cdf3cbffc 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -81,6 +81,10 @@ Config::Config() UPDATER_ENABLED = true; } +#if ENABLE_JAVA_DOWNLOADER + JAVA_DOWNLOADER_ENABLED = true; +#endif + GIT_COMMIT = "@Launcher_GIT_COMMIT@"; GIT_TAG = "@Launcher_GIT_TAG@"; GIT_REFSPEC = "@Launcher_GIT_REFSPEC@"; diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 77b6eef54..e3beb8dbe 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -67,6 +67,7 @@ class Config { QString VERSION_CHANNEL; bool UPDATER_ENABLED = false; + bool JAVA_DOWNLOADER_ENABLED = false; /// A short string identifying this build's platform or distribution. QString BUILD_PLATFORM; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index fcc3c2f3a..f620388dc 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1320,6 +1320,10 @@ if(DEFINED Launcher_APP_BINARY_DEFS) target_compile_definitions(Launcher_logic PRIVATE ${Launcher_APP_BINARY_DEFS}) endif() +if(ENABLE_JAVA_DOWNLOADER) + target_compile_definitions(Launcher_logic PUBLIC ENABLE_JAVA_DOWNLOADER) +endif() + install(TARGETS ${Launcher_Name} BUNDLE DESTINATION "." COMPONENT Runtime LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 95d5f581e..0276daed5 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -35,6 +35,7 @@ */ #include "JavaPage.h" +#include "BuildConfig.h" #include "JavaCommon.h" #include "java/JavaInstall.h" #include "ui/dialogs/CustomMessageBox.h" @@ -62,15 +63,21 @@ JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) { ui->setupUi(this); - ui->managedJavaList->initialize(new JavaInstallList(this, true)); - ui->managedJavaList->selectCurrent(); - ui->managedJavaList->setEmptyString(tr("No java versions are currently available in the meta")); - ui->managedJavaList->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); - connect(ui->autodetectJavaCheckBox, &QCheckBox::stateChanged, this, [this] { - ui->autodownloadCheckBox->setEnabled(ui->autodetectJavaCheckBox->isChecked()); - if (!ui->autodetectJavaCheckBox->isChecked()) - ui->autodownloadCheckBox->setChecked(false); - }); + if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { + ui->managedJavaList->initialize(new JavaInstallList(this, true)); + ui->managedJavaList->selectCurrent(); + ui->managedJavaList->setEmptyString(tr("No java versions are currently available in the meta")); + ui->managedJavaList->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); + connect(ui->autodetectJavaCheckBox, &QCheckBox::stateChanged, this, [this] { + ui->autodownloadCheckBox->setEnabled(ui->autodetectJavaCheckBox->isChecked()); + if (!ui->autodetectJavaCheckBox->isChecked()) + ui->autodownloadCheckBox->setChecked(false); + }); + } else { + ui->autodownloadCheckBox->setHidden(true); + ui->javaDownloadBtn->setHidden(true); + ui->tabWidget->tabBar()->hide(); + } loadSettings(); updateThresholds(); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 50cffc9a7..f2a723b81 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -64,6 +64,8 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance* inst, QWidget* parent) m_settings = inst->settings(); ui->setupUi(this); + ui->javaDownloadBtn->setHidden(!BuildConfig.JAVA_DOWNLOADER_ENABLED); + connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked); connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings); connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings); diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 29357bdab..866d4c182 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -129,8 +129,10 @@ void JavaSettingsWidget::setupUi() m_horizontalBtnLayout = new QHBoxLayout(); m_horizontalBtnLayout->setObjectName(QStringLiteral("horizontalBtnLayout")); - m_javaDownloadBtn = new QPushButton(tr("Download Java"), this); - m_horizontalBtnLayout->addWidget(m_javaDownloadBtn); + if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { + m_javaDownloadBtn = new QPushButton(tr("Download Java"), this); + m_horizontalBtnLayout->addWidget(m_javaDownloadBtn); + } m_verticalLayout->addLayout(m_horizontalBtnLayout); @@ -143,15 +145,17 @@ void JavaSettingsWidget::setupUi() m_autodetectJavaCheckBox->setObjectName("autodetectJavaCheckBox"); m_veriticalJavaLayout->addWidget(m_autodetectJavaCheckBox); - m_autodownloadCheckBox = new QCheckBox(m_autoJavaGroupBox); - m_autodownloadCheckBox->setObjectName("autodownloadCheckBox"); - m_autodownloadCheckBox->setEnabled(false); - m_veriticalJavaLayout->addWidget(m_autodownloadCheckBox); - connect(m_autodetectJavaCheckBox, &QCheckBox::stateChanged, this, [this] { - m_autodownloadCheckBox->setEnabled(m_autodetectJavaCheckBox->isChecked()); - if (!m_autodetectJavaCheckBox->isChecked()) - m_autodownloadCheckBox->setChecked(false); - }); + if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { + m_autodownloadCheckBox = new QCheckBox(m_autoJavaGroupBox); + m_autodownloadCheckBox->setObjectName("autodownloadCheckBox"); + m_autodownloadCheckBox->setEnabled(false); + m_veriticalJavaLayout->addWidget(m_autodownloadCheckBox); + connect(m_autodetectJavaCheckBox, &QCheckBox::stateChanged, this, [this] { + m_autodownloadCheckBox->setEnabled(m_autodetectJavaCheckBox->isChecked()); + if (!m_autodetectJavaCheckBox->isChecked()) + m_autodownloadCheckBox->setChecked(false); + }); + } m_verticalLayout->addWidget(m_autoJavaGroupBox); retranslate(); From ef4e5eb3cf726e3b59f202d6eceee6f53450743e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 18 Mar 2024 19:15:36 +0200 Subject: [PATCH 055/120] fixed java build option Signed-off-by: Trial97 --- buildconfig/BuildConfig.cpp.in | 5 ++--- launcher/CMakeLists.txt | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index cdf3cbffc..a2b5c2187 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -81,9 +81,8 @@ Config::Config() UPDATER_ENABLED = true; } -#if ENABLE_JAVA_DOWNLOADER - JAVA_DOWNLOADER_ENABLED = true; -#endif + #cmakedefine01 ENABLE_JAVA_DOWNLOADER + JAVA_DOWNLOADER_ENABLED = ENABLE_JAVA_DOWNLOADER; GIT_COMMIT = "@Launcher_GIT_COMMIT@"; GIT_TAG = "@Launcher_GIT_TAG@"; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index f620388dc..fcc3c2f3a 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1320,10 +1320,6 @@ if(DEFINED Launcher_APP_BINARY_DEFS) target_compile_definitions(Launcher_logic PRIVATE ${Launcher_APP_BINARY_DEFS}) endif() -if(ENABLE_JAVA_DOWNLOADER) - target_compile_definitions(Launcher_logic PUBLIC ENABLE_JAVA_DOWNLOADER) -endif() - install(TARGETS ${Launcher_Name} BUNDLE DESTINATION "." COMPONENT Runtime LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime From 09c2c6793b52639f86f2edead268b51ad4b5fffc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 20 Mar 2024 00:15:02 +0200 Subject: [PATCH 056/120] Improve UI Signed-off-by: Trial97 --- launcher/BaseVersionList.cpp | 1 - launcher/BaseVersionList.h | 1 - launcher/CMakeLists.txt | 5 +- launcher/VersionProxyModel.cpp | 9 - launcher/VersionProxyModel.h | 2 +- launcher/java/JavaMetadata.cpp | 2 +- launcher/java/JavaMetadata.h | 2 +- launcher/minecraft/OneSixVersionFormat.cpp | 9 +- launcher/minecraft/VersionFile.h | 2 +- launcher/minecraft/launch/AutoInstallJava.cpp | 60 +++-- launcher/ui/java/InstallJavaDialog.cpp | 234 ++++++++++++++++++ .../{JavaDownloader.h => InstallJavaDialog.h} | 28 +-- launcher/ui/java/JavaDownloader.cpp | 110 -------- launcher/ui/java/JavaDownloader.ui | 100 -------- launcher/ui/java/VersionList.cpp | 14 +- launcher/ui/pages/global/JavaPage.cpp | 4 +- .../pages/instance/InstanceSettingsPage.cpp | 4 +- launcher/ui/widgets/JavaSettingsWidget.cpp | 4 +- 18 files changed, 295 insertions(+), 296 deletions(-) create mode 100644 launcher/ui/java/InstallJavaDialog.cpp rename launcher/ui/java/{JavaDownloader.h => InstallJavaDialog.h} (63%) delete mode 100644 launcher/ui/java/JavaDownloader.cpp delete mode 100644 launcher/ui/java/JavaDownloader.ui diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp index 1456a17bd..afee8388a 100644 --- a/launcher/BaseVersionList.cpp +++ b/launcher/BaseVersionList.cpp @@ -112,6 +112,5 @@ QHash BaseVersionList::roleNames() const roles.insert(PathRole, "path"); roles.insert(JavaNameRole, "javaName"); roles.insert(CPUArchitectureRole, "architecture"); - roles.insert(JavaVendorRole, "javaVendor"); return roles; } diff --git a/launcher/BaseVersionList.h b/launcher/BaseVersionList.h index 7517c71b4..bc37e9e53 100644 --- a/launcher/BaseVersionList.h +++ b/launcher/BaseVersionList.h @@ -50,7 +50,6 @@ class BaseVersionList : public QAbstractListModel { PathRole, JavaNameRole, CPUArchitectureRole, - JavaVendorRole, SortRole }; using RoleList = QList; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index fcc3c2f3a..dd493682e 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -440,8 +440,8 @@ set(JAVA_SOURCES java/download/ManifestDownloadTask.cpp java/download/ManifestDownloadTask.h - ui/java/JavaDownloader.h - ui/java/JavaDownloader.cpp + ui/java/InstallJavaDialog.h + ui/java/InstallJavaDialog.cpp ui/java/VersionList.h ui/java/VersionList.cpp ) @@ -1194,7 +1194,6 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ScrollMessageBox.ui ui/dialogs/BlockedModsDialog.ui ui/dialogs/ChooseProviderDialog.ui - ui/java/JavaDownloader.ui ) qt_wrap_ui(PRISM_UPDATE_UI diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index ed4c0767d..070e952a4 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -116,8 +116,6 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("Type"); case CPUArchitecture: return tr("Architecture"); - case JavaVendor: - return tr("Vendor"); case Path: return tr("Path"); case JavaName: @@ -137,8 +135,6 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("The version's type"); case CPUArchitecture: return tr("CPU Architecture"); - case JavaVendor: - return tr("Java vendor"); case Path: return tr("Filesystem path to this version"); case JavaName: @@ -175,8 +171,6 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const return sourceModel()->data(parentIndex, BaseVersionList::TypeRole); case CPUArchitecture: return sourceModel()->data(parentIndex, BaseVersionList::CPUArchitectureRole); - case JavaVendor: - return sourceModel()->data(parentIndex, BaseVersionList::JavaVendorRole); case Path: return sourceModel()->data(parentIndex, BaseVersionList::PathRole); case JavaName: @@ -323,9 +317,6 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw) if (roles.contains(BaseVersionList::CPUArchitectureRole)) { m_columns.push_back(CPUArchitecture); } - if (roles.contains(BaseVersionList::JavaVendorRole)) { - m_columns.push_back(JavaVendor); - } if (roles.contains(BaseVersionList::PathRole)) { m_columns.push_back(Path); } diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index 5a1017bee..cb55b7f14 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -9,7 +9,7 @@ class VersionFilterModel; class VersionProxyModel : public QAbstractProxyModel { Q_OBJECT public: - enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName, JavaVendor }; + enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName }; using FilterMap = QHash>; public: diff --git a/launcher/java/JavaMetadata.cpp b/launcher/java/JavaMetadata.cpp index b73c54fe6..e721947a7 100644 --- a/launcher/java/JavaMetadata.cpp +++ b/launcher/java/JavaMetadata.cpp @@ -52,9 +52,9 @@ MetadataPtr parseJavaMeta(const QJsonObject& in) meta->vendor = Json::ensureString(in, "vendor", ""); meta->url = Json::ensureString(in, "url", ""); meta->releaseTime = timeFromS3Time(Json::ensureString(in, "releaseTime", "")); - meta->recommended = Json::ensureBoolean(in, "recommended", false); meta->downloadType = parseDownloadType(Json::ensureString(in, "downloadType", "")); meta->packageType = Json::ensureString(in, "packageType", ""); + meta->runtimeOS = Json::ensureString(in, "runtimeOS", "unknown"); if (in.contains("checksum")) { auto obj = Json::requireObject(in, "checksum"); diff --git a/launcher/java/JavaMetadata.h b/launcher/java/JavaMetadata.h index 640a412f1..5281f2e27 100644 --- a/launcher/java/JavaMetadata.h +++ b/launcher/java/JavaMetadata.h @@ -50,10 +50,10 @@ class Metadata : public BaseVersion { QDateTime releaseTime; QString checksumType; QString checksumHash; - bool recommended; DownloadType downloadType; QString packageType; JavaVersion version; + QString runtimeOS; }; using MetadataPtr = std::shared_ptr; diff --git a/launcher/minecraft/OneSixVersionFormat.cpp b/launcher/minecraft/OneSixVersionFormat.cpp index 56e9c8ca2..bd587beb2 100644 --- a/launcher/minecraft/OneSixVersionFormat.cpp +++ b/launcher/minecraft/OneSixVersionFormat.cpp @@ -258,14 +258,9 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument& doc } if (root.contains("runtimes")) { - auto runtimes = requireObject(root, "runtimes"); out->runtimes = {}; - for (auto key : runtimes.keys()) { - QList list; - for (auto runtime : ensureArray(runtimes, key)) { - list.append(Java::parseJavaMeta(ensureObject(runtime))); - } - out->runtimes[key] = list; + for (auto runtime : ensureArray(root, "runtimes")) { + out->runtimes.append(Java::parseJavaMeta(ensureObject(runtime))); } } diff --git a/launcher/minecraft/VersionFile.h b/launcher/minecraft/VersionFile.h index a9c1473d2..85ac55426 100644 --- a/launcher/minecraft/VersionFile.h +++ b/launcher/minecraft/VersionFile.h @@ -155,7 +155,7 @@ class VersionFile : public ProblemContainer { /// is volatile -- may be removed as soon as it is no longer needed by something else bool m_volatile = false; - QHash> runtimes; + QList runtimes; public: // Mojang: DEPRECATED list of 'downloads' - client jar, server jar, windows server exe, maybe more. diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index ab68910a7..3ae6ffa88 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -145,39 +145,35 @@ void AutoInstallJava::setJavaPathFromPartial() void AutoInstallJava::downloadJava(Meta::Version::Ptr version, QString javaName) { auto runtimes = version->data()->runtimes; - if (runtimes.contains(m_supported_arch)) { - for (auto java : runtimes.value(m_supported_arch)) { - if (java->name() == javaName) { - QDir javaDir(APPLICATION->javaPath()); - auto final_path = javaDir.absoluteFilePath(java->m_name); - switch (java->downloadType) { - case Java::DownloadType::Manifest: - m_current_task = - makeShared(java->url, final_path, java->checksumType, java->checksumHash); - break; - case Java::DownloadType::Archive: - m_current_task = - makeShared(java->url, final_path, java->checksumType, java->checksumHash); - break; - } - auto deletePath = [final_path] { FS::deletePath(final_path); }; - connect(m_current_task.get(), &Task::failed, this, [this, deletePath](QString reason) { - deletePath(); - emitFailed(reason); - }); - connect(this, &Task::aborted, this, [this, deletePath] { - m_current_task->abort(); - 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; + for (auto java : runtimes) { + if (java->runtimeOS == m_supported_arch && java->name() == javaName) { + QDir javaDir(APPLICATION->javaPath()); + auto final_path = javaDir.absoluteFilePath(java->m_name); + switch (java->downloadType) { + case Java::DownloadType::Manifest: + m_current_task = makeShared(java->url, final_path, java->checksumType, java->checksumHash); + break; + case Java::DownloadType::Archive: + m_current_task = makeShared(java->url, final_path, java->checksumType, java->checksumHash); + break; } + auto deletePath = [final_path] { FS::deletePath(final_path); }; + connect(m_current_task.get(), &Task::failed, this, [this, deletePath](QString reason) { + deletePath(); + emitFailed(reason); + }); + connect(this, &Task::aborted, this, [this, deletePath] { + m_current_task->abort(); + 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(); diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp new file mode 100644 index 000000000..054e5cece --- /dev/null +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2024 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "InstallJavaDialog.h" + +#include +#include +#include +#include + +#include "Application.h" +#include "FileSystem.h" +#include "java/download/ArchiveDownloadTask.h" +#include "java/download/ManifestDownloadTask.h" +#include "meta/Index.h" +#include "meta/VersionList.h" +#include "ui/dialogs/ProgressDialog.h" +#include "ui/java/VersionList.h" +#include "ui/widgets/PageContainer.h" +#include "ui/widgets/VersionSelectWidget.h" + +class InstallLoaderPage : public QWidget, public BasePage { + public: + Q_OBJECT + public: + explicit InstallLoaderPage(const QString& id, const QString& iconName, const QString& name, QWidget* parent = nullptr) + : QWidget(parent), uid(id), iconName(iconName), name(name) + { + setObjectName(QStringLiteral("VersionSelectWidget")); + horizontalLayout = new QHBoxLayout(this); + horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + horizontalLayout->setContentsMargins(0, 0, 0, 0); + + majorVersionSelect = new VersionSelectWidget(this); + majorVersionSelect->selectCurrent(); + majorVersionSelect->setEmptyString(tr("No java versions are currently available in the meta.")); + majorVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); + horizontalLayout->addWidget(majorVersionSelect, 1); + + javaVersionSelect = new VersionSelectWidget(this); + javaVersionSelect->setEmptyString(tr("No java versions are currently available for your OS.")); + javaVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); + horizontalLayout->addWidget(javaVersionSelect, 4); + connect(majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallLoaderPage::setSelectedVersion); + connect(javaVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallLoaderPage::selectedVersionChanged); + + QMetaObject::connectSlotsByName(this); + } + ~InstallLoaderPage() + { + delete horizontalLayout; + delete majorVersionSelect; + delete javaVersionSelect; + } + + //! loads the list if needed. + void initialize(Meta::VersionList::Ptr vlist) + { + vlist->setProvidedRoles({ BaseVersionList::VersionRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole }); + majorVersionSelect->initialize(vlist.get()); + } + + void setSelectedVersion(BaseVersion::Ptr version) + { + auto dcast = std::dynamic_pointer_cast(version); + if (!dcast) { + return; + } + javaVersionSelect->initialize(new Java::VersionList(dcast, this)); + javaVersionSelect->selectCurrent(); + } + + QString id() const override { return uid; } + QString displayName() const override { return name; } + QIcon icon() const override { return APPLICATION->getThemedIcon(iconName); } + + void openedImpl() override + { + if (loaded) + return; + + const auto versions = APPLICATION->metadataIndex()->get(uid); + if (!versions) + return; + + initialize(versions); + loaded = true; + } + + void setParentContainer(BasePageContainer* container) override + { + auto dialog = dynamic_cast(dynamic_cast(container)->parent()); + connect(javaVersionSelect->view(), &QAbstractItemView::doubleClicked, dialog, &QDialog::accept); + } + + BaseVersion::Ptr selectedVersion() const { return javaVersionSelect->selectedVersion(); } + void selectSearch() { javaVersionSelect->selectSearch(); } + void loadList() + { + majorVersionSelect->loadList(); + javaVersionSelect->loadList(); + } + signals: + void selectedVersionChanged(BaseVersion::Ptr version); + + private: + const QString uid; + const QString iconName; + const QString name; + bool loaded = false; + + QHBoxLayout* horizontalLayout = nullptr; + VersionSelectWidget* majorVersionSelect = nullptr; + VersionSelectWidget* javaVersionSelect = nullptr; +}; + +static InstallLoaderPage* pageCast(BasePage* page) +{ + auto result = dynamic_cast(page); + Q_ASSERT(result != nullptr); + return result; +} +namespace Java { + +InstallDialog::InstallDialog(const QString& uid, QWidget* parent) + : QDialog(parent), container(new PageContainer(this, QString(), this)), buttons(new QDialogButtonBox(this)) +{ + auto layout = new QVBoxLayout(this); + + container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + layout->addWidget(container); + + auto buttonLayout = new QHBoxLayout(this); + + auto refreshButton = new QPushButton(tr("&Refresh"), this); + connect(refreshButton, &QPushButton::clicked, this, [this] { pageCast(container->selectedPage())->loadList(); }); + buttonLayout->addWidget(refreshButton); + + buttons->setOrientation(Qt::Horizontal); + buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + buttons->button(QDialogButtonBox::Ok)->setText(tr("Download")); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + buttonLayout->addWidget(buttons); + + layout->addLayout(buttonLayout); + + setWindowTitle(dialogTitle()); + setWindowModality(Qt::WindowModal); + resize(840, 480); + + for (BasePage* page : container->getPages()) { + if (page->id() == uid) + container->selectPage(page->id()); + + connect(pageCast(page), &InstallLoaderPage::selectedVersionChanged, this, [this, page] { + if (page->id() == container->selectedPage()->id()) + validate(container->selectedPage()); + }); + } + connect(container, &PageContainer::selectedPageChanged, this, [this](BasePage* previous, BasePage* current) { validate(current); }); + pageCast(container->selectedPage())->selectSearch(); + validate(container->selectedPage()); +} + +QList InstallDialog::getPages() +{ + return { + // NeoForge + new InstallLoaderPage("net.minecraft.java", "", tr("Mojang")), + // Forge + new InstallLoaderPage("net.adoptium.java", "", tr("Adoptium")), + // Fabric + new InstallLoaderPage("com.azul.java", "", tr("Azul")), + }; +} + +QString InstallDialog::dialogTitle() +{ + return tr("Install Loader"); +} + +void InstallDialog::validate(BasePage* page) +{ + buttons->button(QDialogButtonBox::Ok)->setEnabled(pageCast(page)->selectedVersion() != nullptr); +} + +void InstallDialog::done(int result) +{ + if (result == Accepted) { + auto* page = pageCast(container->selectedPage()); + if (page->selectedVersion()) { + auto meta = std::dynamic_pointer_cast(page->selectedVersion()); + if (meta) { + Task::Ptr task; + auto final_path = FS::PathCombine(APPLICATION->javaPath(), meta->m_name); + switch (meta->downloadType) { + case Java::DownloadType::Manifest: + task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); + break; + case Java::DownloadType::Archive: + task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); + break; + } + auto deletePath = [final_path] { FS::deletePath(final_path); }; + connect(task.get(), &Task::failed, this, deletePath); + connect(task.get(), &Task::aborted, this, deletePath); + ProgressDialog pg(this); + pg.setSkipButton(true, tr("Abort")); + pg.execWithTask(task.get()); + } + } + } + + QDialog::done(result); +} +} // namespace Java + +#include "InstallJavaDialog.moc" \ No newline at end of file diff --git a/launcher/ui/java/JavaDownloader.h b/launcher/ui/java/InstallJavaDialog.h similarity index 63% rename from launcher/ui/java/JavaDownloader.h rename to launcher/ui/java/InstallJavaDialog.h index b8bdde41a..e228adf21 100644 --- a/launcher/ui/java/JavaDownloader.h +++ b/launcher/ui/java/InstallJavaDialog.h @@ -19,30 +19,28 @@ #pragma once #include -#include "BaseVersion.h" +#include "ui/pages/BasePageProvider.h" -namespace Ui { -class JavaDownloader; -} +class MinecraftInstance; +class PageContainer; +class PackProfile; +class QDialogButtonBox; namespace Java { - -class Downloader : public QDialog { +class InstallDialog final : public QDialog, protected BasePageProvider { Q_OBJECT public: - explicit Downloader(QWidget* parent = 0); - ~Downloader(); + explicit InstallDialog(const QString& uid = QString(), QWidget* parent = nullptr); - void accept(); + QList getPages() override; + QString dialogTitle() override; - public slots: - void refresh(); - - protected slots: - void setSelectedVersion(BaseVersion::Ptr version); + void validate(BasePage* page); + void done(int result) override; private: - Ui::JavaDownloader* ui; + PageContainer* container; + QDialogButtonBox* buttons; }; } // namespace Java diff --git a/launcher/ui/java/JavaDownloader.cpp b/launcher/ui/java/JavaDownloader.cpp deleted file mode 100644 index 24918dd76..000000000 --- a/launcher/ui/java/JavaDownloader.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2024 Trial97 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "JavaDownloader.h" - -#include - -#include - -#include "Application.h" -#include "BaseVersionList.h" -#include "FileSystem.h" -#include "QObjectPtr.h" -#include "SysInfo.h" - -#include "java/JavaMetadata.h" -#include "java/download/ArchiveDownloadTask.h" -#include "java/download/ManifestDownloadTask.h" - -#include "meta/Index.h" -#include "meta/Version.h" - -#include "meta/VersionList.h" -#include "ui/dialogs/ProgressDialog.h" -#include "ui/java/VersionList.h" -#include "ui_JavaDownloader.h" - -namespace Java { - -Downloader::Downloader(QWidget* parent) : QDialog(parent), ui(new Ui::JavaDownloader) -{ - ui->setupUi(this); - auto versionList = APPLICATION->metadataIndex()->get("net.minecraft.java"); - versionList->setProvidedRoles({ BaseVersionList::VersionRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole }); - ui->majorVersionSelect->initialize(versionList.get()); - ui->majorVersionSelect->selectCurrent(); - ui->majorVersionSelect->setEmptyString(tr("No java versions are currently available in the meta.")); - ui->majorVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); - - ui->javaVersionSelect->setEmptyString(tr("No java versions are currently available for your OS.")); - ui->javaVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); - - ui->buttonBox->button(QDialogButtonBox::Reset)->setText(tr("Refresh")); - ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Download")); - - connect(ui->majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &Downloader::setSelectedVersion); - auto reset = ui->buttonBox->button(QDialogButtonBox::Reset); - connect(reset, &QPushButton::clicked, this, &Downloader::refresh); -} - -Downloader::~Downloader() -{ - delete ui; -} - -void Downloader::setSelectedVersion(BaseVersion::Ptr version) -{ - auto dcast = std::dynamic_pointer_cast(version); - if (!dcast) { - return; - } - ui->javaVersionSelect->initialize(new Java::VersionList(dcast, this)); - ui->javaVersionSelect->selectCurrent(); -} - -void Downloader::accept() -{ - auto meta = std::dynamic_pointer_cast(ui->javaVersionSelect->selectedVersion()); - if (!meta) { - return; - } - Task::Ptr task; - auto final_path = FS::PathCombine(APPLICATION->javaPath(), meta->m_name); - switch (meta->downloadType) { - case Java::DownloadType::Manifest: - task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); - break; - case Java::DownloadType::Archive: - task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); - break; - } - auto deletePath = [final_path] { FS::deletePath(final_path); }; - connect(task.get(), &Task::failed, this, deletePath); - connect(task.get(), &Task::aborted, this, deletePath); - ProgressDialog pg(this); - pg.setSkipButton(true, tr("Abort")); - pg.execWithTask(task.get()); - QDialog::accept(); -} - -void Downloader::refresh() -{ - ui->majorVersionSelect->loadList(); -} -} // namespace Java diff --git a/launcher/ui/java/JavaDownloader.ui b/launcher/ui/java/JavaDownloader.ui deleted file mode 100644 index 3f6a8adc6..000000000 --- a/launcher/ui/java/JavaDownloader.ui +++ /dev/null @@ -1,100 +0,0 @@ - - - JavaDownloader - - - - 0 - 0 - 821 - 593 - - - - Dialog - - - - - - - - Major - - - - - - - - - - - - Runtime - - - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset - - - - - - - - VersionSelectWidget - QWidget -
ui/widgets/VersionSelectWidget.h
- 1 -
-
- - - - buttonBox - accepted() - JavaDownloader - accept() - - - 257 - 583 - - - 157 - 274 - - - - - buttonBox - rejected() - JavaDownloader - reject() - - - 325 - 583 - - - 286 - 274 - - - - -
diff --git a/launcher/ui/java/VersionList.cpp b/launcher/ui/java/VersionList.cpp index dc454f264..78448ddaf 100644 --- a/launcher/ui/java/VersionList.cpp +++ b/launcher/ui/java/VersionList.cpp @@ -75,11 +75,9 @@ QVariant VersionList::data(const QModelIndex& index, int role) const case VersionRole: return version->version.toString(); case RecommendedRole: - return version->recommended; + return false; // do not recommend any version case JavaNameRole: return version->name(); - case JavaVendorRole: - return version->vendor; case TypeRole: return version->packageType; case Meta::VersionList::TimeRole: @@ -91,8 +89,7 @@ QVariant VersionList::data(const QModelIndex& index, int role) const BaseVersionList::RoleList VersionList::providesRoles() const { - return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, - JavaNameRole, JavaVendorRole, TypeRole, Meta::VersionList::TimeRole }; + return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, JavaNameRole, TypeRole, Meta::VersionList::TimeRole }; } bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right) @@ -109,11 +106,12 @@ void VersionList::sortVersions() QString versionStr = SysInfo::getSupportedJavaArchitecture(); beginResetModel(); auto runtimes = m_version->data()->runtimes; - if (!versionStr.isEmpty() && !runtimes.isEmpty() && runtimes.contains(versionStr)) { - m_vlist = runtimes.value(versionStr); + m_vlist = {}; + if (!versionStr.isEmpty() && !runtimes.isEmpty()) { + std::copy_if(runtimes.begin(), runtimes.end(), std::back_inserter(m_vlist), + [versionStr](Java::MetadataPtr val) { return val->runtimeOS == versionStr; }); std::sort(m_vlist.begin(), m_vlist.end(), sortJavas); } else { - m_vlist = {}; qWarning() << "No Java versions found for your operating system." << SysInfo::currentSystem() << " " << SysInfo::useQTForArch(); } endResetModel(); diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 0276daed5..41a666cf2 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -39,7 +39,7 @@ #include "JavaCommon.h" #include "java/JavaInstall.h" #include "ui/dialogs/CustomMessageBox.h" -#include "ui/java/JavaDownloader.h" +#include "ui/java/InstallJavaDialog.h" #include "ui_JavaPage.h" #include @@ -201,7 +201,7 @@ void JavaPage::on_javaTestBtn_clicked() void JavaPage::on_javaDownloadBtn_clicked() { - auto jdialog = new Java::Downloader(this); + auto jdialog = new Java::InstallDialog({}, this); jdialog->exec(); ui->managedJavaList->loadList(); } diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 0b731e64f..c248a47f7 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -37,7 +37,7 @@ #include "InstanceSettingsPage.h" #include "ui/dialogs/CustomMessageBox.h" -#include "ui/java/JavaDownloader.h" +#include "ui/java/InstallJavaDialog.h" #include "ui_InstanceSettingsPage.h" #include @@ -394,7 +394,7 @@ void InstanceSettingsPage::loadSettings() void InstanceSettingsPage::on_javaDownloadBtn_clicked() { - auto jdialog = new Java::Downloader(this); + auto jdialog = new Java::InstallDialog({}, this); jdialog->exec(); } diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 866d4c182..e2e498067 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -21,7 +21,7 @@ #include "java/JavaUtils.h" #include "ui/dialogs/CustomMessageBox.h" -#include "ui/java/JavaDownloader.h" +#include "ui/java/InstallJavaDialog.h" #include "ui/widgets/VersionSelectWidget.h" #include "Application.h" @@ -351,7 +351,7 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked() void JavaSettingsWidget::on_javaDownloadBtn_clicked() { - auto jdialog = new Java::Downloader(this); + auto jdialog = new Java::InstallDialog({}, this); jdialog->exec(); } From 5f8269f5e1ac41b29ed386e1a675e972c8d5624e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 20 Mar 2024 00:29:46 +0200 Subject: [PATCH 057/120] Small class rename Signed-off-by: Trial97 --- launcher/ui/java/InstallJavaDialog.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index 054e5cece..40616aafe 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -34,11 +34,11 @@ #include "ui/widgets/PageContainer.h" #include "ui/widgets/VersionSelectWidget.h" -class InstallLoaderPage : public QWidget, public BasePage { +class InstallJavaPage : public QWidget, public BasePage { public: Q_OBJECT public: - explicit InstallLoaderPage(const QString& id, const QString& iconName, const QString& name, QWidget* parent = nullptr) + explicit InstallJavaPage(const QString& id, const QString& iconName, const QString& name, QWidget* parent = nullptr) : QWidget(parent), uid(id), iconName(iconName), name(name) { setObjectName(QStringLiteral("VersionSelectWidget")); @@ -56,12 +56,12 @@ class InstallLoaderPage : public QWidget, public BasePage { javaVersionSelect->setEmptyString(tr("No java versions are currently available for your OS.")); javaVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); horizontalLayout->addWidget(javaVersionSelect, 4); - connect(majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallLoaderPage::setSelectedVersion); - connect(javaVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallLoaderPage::selectedVersionChanged); + connect(majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::setSelectedVersion); + connect(javaVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectedVersionChanged); QMetaObject::connectSlotsByName(this); } - ~InstallLoaderPage() + ~InstallJavaPage() { delete horizontalLayout; delete majorVersionSelect; @@ -129,9 +129,9 @@ class InstallLoaderPage : public QWidget, public BasePage { VersionSelectWidget* javaVersionSelect = nullptr; }; -static InstallLoaderPage* pageCast(BasePage* page) +static InstallJavaPage* pageCast(BasePage* page) { - auto result = dynamic_cast(page); + auto result = dynamic_cast(page); Q_ASSERT(result != nullptr); return result; } @@ -168,7 +168,7 @@ InstallDialog::InstallDialog(const QString& uid, QWidget* parent) if (page->id() == uid) container->selectPage(page->id()); - connect(pageCast(page), &InstallLoaderPage::selectedVersionChanged, this, [this, page] { + connect(pageCast(page), &InstallJavaPage::selectedVersionChanged, this, [this, page] { if (page->id() == container->selectedPage()->id()) validate(container->selectedPage()); }); @@ -182,11 +182,11 @@ QList InstallDialog::getPages() { return { // NeoForge - new InstallLoaderPage("net.minecraft.java", "", tr("Mojang")), + new InstallJavaPage("net.minecraft.java", "", tr("Mojang")), // Forge - new InstallLoaderPage("net.adoptium.java", "", tr("Adoptium")), + new InstallJavaPage("net.adoptium.java", "", tr("Adoptium")), // Fabric - new InstallLoaderPage("com.azul.java", "", tr("Azul")), + new InstallJavaPage("com.azul.java", "", tr("Azul")), }; } From 703470e57d615b1bb1998a253865c8fe7fadcccd Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 20 Mar 2024 08:24:40 +0200 Subject: [PATCH 058/120] Hopefully fix codeql Signed-off-by: Trial97 --- launcher/ui/java/InstallJavaDialog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/java/InstallJavaDialog.h b/launcher/ui/java/InstallJavaDialog.h index e228adf21..c98c1deae 100644 --- a/launcher/ui/java/InstallJavaDialog.h +++ b/launcher/ui/java/InstallJavaDialog.h @@ -27,7 +27,7 @@ class PackProfile; class QDialogButtonBox; namespace Java { -class InstallDialog final : public QDialog, protected BasePageProvider { +class InstallDialog final : public QDialog, public BasePageProvider { Q_OBJECT public: From 1c809f0fb1ef477d0315a7d1af174852b3b831e8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 20 Mar 2024 17:39:10 +0200 Subject: [PATCH 059/120] Added more logs for auto java install Signed-off-by: Trial97 --- launcher/minecraft/launch/AutoInstallJava.cpp | 19 ++++++++++++++++++- launcher/ui/java/InstallJavaDialog.cpp | 1 + launcher/ui/java/InstallJavaDialog.h | 2 +- launcher/ui/pages/global/JavaPage.cpp | 5 ++--- launcher/ui/pages/global/JavaPage.ui | 8 -------- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index 3ae6ffa88..1dc91003f 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -91,7 +91,21 @@ void AutoInstallJava::executeTask() emit progressReportingRequest(); return; } + if (m_supported_arch.isEmpty()) { + emit logLine(tr("Your system(%1 %2) is not compatible with auto java download. 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 informtation is old or doesn't have the information necesary to determine what 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)) { @@ -136,7 +150,8 @@ void AutoInstallJava::setJavaPathFromPartial() if (QFileInfo::exists(finalPath)) { setJavaPath(finalPath); } else { - emit logLine(tr("No compatible java version was found. Using the default one."), MessageLevel::Warning); + emit logLine(tr("No compatible java version was found(the binary file doesn't exists). Using the default one."), + MessageLevel::Warning); emitSucceeded(); } return; @@ -188,6 +203,8 @@ void AutoInstallJava::tryNextMajorJava() auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName(); auto majorJavaVersions = packProfile->getProfile()->getCompatibleJavaMajors(); if (m_majorJavaVersionIndex >= majorJavaVersions.length()) { + emit logLine(tr("No Java versions found for your operating system: %1 %2").arg(SysInfo::currentSystem(), SysInfo::useQTForArch()), + MessageLevel::Warning); emit logLine(tr("No compatible java version was found. Using the default one."), MessageLevel::Warning); emitSucceeded(); return; diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index 40616aafe..874fc9133 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -72,6 +72,7 @@ class InstallJavaPage : public QWidget, public BasePage { void initialize(Meta::VersionList::Ptr vlist) { vlist->setProvidedRoles({ BaseVersionList::VersionRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole }); + vlist->sort(1); majorVersionSelect->initialize(vlist.get()); } diff --git a/launcher/ui/java/InstallJavaDialog.h b/launcher/ui/java/InstallJavaDialog.h index c98c1deae..525e750aa 100644 --- a/launcher/ui/java/InstallJavaDialog.h +++ b/launcher/ui/java/InstallJavaDialog.h @@ -27,7 +27,7 @@ class PackProfile; class QDialogButtonBox; namespace Java { -class InstallDialog final : public QDialog, public BasePageProvider { +class InstallDialog final : public QDialog, private BasePageProvider { Q_OBJECT public: diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 41a666cf2..6d8b95c24 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -66,8 +66,8 @@ JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { ui->managedJavaList->initialize(new JavaInstallList(this, true)); ui->managedJavaList->selectCurrent(); - ui->managedJavaList->setEmptyString(tr("No java versions are currently available in the meta")); - ui->managedJavaList->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); + ui->managedJavaList->setEmptyString(tr("No managed java versions are installed")); + ui->managedJavaList->setEmptyErrorString(tr("Couldn't load the managed java list!")); connect(ui->autodetectJavaCheckBox, &QCheckBox::stateChanged, this, [this] { ui->autodownloadCheckBox->setEnabled(ui->autodetectJavaCheckBox->isChecked()); if (!ui->autodetectJavaCheckBox->isChecked()) @@ -75,7 +75,6 @@ JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) }); } else { ui->autodownloadCheckBox->setHidden(true); - ui->javaDownloadBtn->setHidden(true); ui->tabWidget->tabBar()->hide(); } diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index dc1668ee3..c8f62e075 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -178,13 +178,6 @@ - - - - Download Java - - - @@ -424,7 +417,6 @@ permGenSpinBox javaPathTextBox javaBrowseBtn - javaDownloadBtn javaDetectBtn javaTestBtn skipCompatibilityCheckbox From ab7fc2e46cd1ebe3d29436c8939de57d681a24a2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 21 Mar 2024 00:42:04 +0200 Subject: [PATCH 060/120] Fixed archive java download Signed-off-by: Trial97 --- launcher/MMCZip.cpp | 4 ++++ launcher/java/download/ArchiveDownloadTask.cpp | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 265eb8b7a..33f5f88fc 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -510,6 +510,10 @@ bool ExportToZipTask::abort() void ExtractZipTask::executeTask() { + if (!m_input->isOpen() && !m_input->open(QuaZip::mdUnzip)) { + emitFailed(tr("Unable to open supplied zip file.")); + return; + } m_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return extractZip(); }); connect(&m_zip_watcher, &QFutureWatcher::finished, this, &ExtractZipTask::finish); m_zip_watcher.setFuture(m_zip_future); diff --git a/launcher/java/download/ArchiveDownloadTask.cpp b/launcher/java/download/ArchiveDownloadTask.cpp index 34f60260e..d62d4d8e2 100644 --- a/launcher/java/download/ArchiveDownloadTask.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -35,7 +35,7 @@ void ArchiveDownloadTask::executeTask() // JRE found ! download the zip setStatus(tr("Downloading Java")); - MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("java", m_url.toLocalFile()); + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("java", m_url.fileName()); auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); auto action = Net::Download::makeCached(m_url, entry); @@ -70,12 +70,16 @@ void ArchiveDownloadTask::extractJava(QString input) { setStatus(tr("Extracting java")); auto zip = std::make_shared(input); + if (!zip->open(QuaZip::mdUnzip)) { + emitFailed(tr("Unable to open supplied zip file.")); + return; + } auto files = zip->getFileNameList(); if (files.isEmpty()) { emitFailed("Empty archive"); return; } - auto zipTask = makeShared(input, m_final_path, files[0]); + auto zipTask = makeShared(zip, m_final_path, files[0]); auto progressStep = std::make_shared(); connect(zipTask.get(), &Task::finished, this, [this, progressStep] { From 1a6dfd04d66edb667f2ceb6646620b219dc17daf Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 21 Mar 2024 19:46:57 +0200 Subject: [PATCH 061/120] Made tar.gz parser Signed-off-by: Trial97 --- launcher/Application.cpp | 1 + launcher/BaseVersionList.cpp | 9 + launcher/BaseVersionList.h | 1 + launcher/CMakeLists.txt | 2 + launcher/FileSystem.cpp | 3 + launcher/Untar.cpp | 262 ++++++++++++++++++ launcher/Untar.h | 46 +++ launcher/VersionProxyModel.cpp | 9 + launcher/VersionProxyModel.h | 2 +- .../java/download/ArchiveDownloadTask.cpp | 23 ++ launcher/meta/VersionList.cpp | 7 + .../minecraft/launch/VerifyJavaInstall.cpp | 1 - launcher/ui/java/InstallJavaDialog.cpp | 12 +- launcher/ui/java/VersionList.cpp | 7 + launcher/ui/widgets/JavaSettingsWidget.cpp | 2 +- 15 files changed, 381 insertions(+), 6 deletions(-) create mode 100644 launcher/Untar.cpp create mode 100644 launcher/Untar.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index b0929a0ae..f7fa3aedd 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -869,6 +869,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_metacache->addBase("translations", QDir("translations").absolutePath()); m_metacache->addBase("icons", QDir("cache/icons").absolutePath()); m_metacache->addBase("meta", QDir("meta").absolutePath()); + m_metacache->addBase("java", QDir("cache/java").absolutePath()); m_metacache->Load(); qDebug() << "<> Cache initialized."; } diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp index afee8388a..22077c962 100644 --- a/launcher/BaseVersionList.cpp +++ b/launcher/BaseVersionList.cpp @@ -78,6 +78,14 @@ QVariant BaseVersionList::data(const QModelIndex& index, int role) const case TypeRole: return version->typeString(); + case JavaMajorRole: { + auto major = version->name(); + if (major.startsWith("java")) { + major = "Java " + major.mid(4); + } + return major; + } + default: return QVariant(); } @@ -112,5 +120,6 @@ QHash BaseVersionList::roleNames() const roles.insert(PathRole, "path"); roles.insert(JavaNameRole, "javaName"); roles.insert(CPUArchitectureRole, "architecture"); + roles.insert(JavaMajorRole, "javaMajor"); return roles; } diff --git a/launcher/BaseVersionList.h b/launcher/BaseVersionList.h index bc37e9e53..673d13562 100644 --- a/launcher/BaseVersionList.h +++ b/launcher/BaseVersionList.h @@ -49,6 +49,7 @@ class BaseVersionList : public QAbstractListModel { BranchRole, PathRole, JavaNameRole, + JavaMajorRole, CPUArchitectureRole, SortRole }; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index dd493682e..4f8ab598e 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -24,6 +24,8 @@ set(CORE_SOURCES NullInstance.h MMCZip.h MMCZip.cpp + Untar.h + Untar.cpp StringUtils.h StringUtils.cpp QVariantUtils.h diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index f9be91a2a..8320dfe40 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -276,6 +276,9 @@ bool ensureFolderPathExists(const QFileInfo folderPath) { QDir dir; QString ensuredPath = folderPath.filePath(); + if (folderPath.exists()) + return true; + bool success = dir.mkpath(ensuredPath); return success; } diff --git a/launcher/Untar.cpp b/launcher/Untar.cpp new file mode 100644 index 000000000..521c504a6 --- /dev/null +++ b/launcher/Untar.cpp @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023-2024 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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 "Untar.h" +#include +#include +#include +#include +#include +#include +#include +#include "FileSystem.h" + +// adaptation of the: +// - https://github.com/madler/zlib/blob/develop/contrib/untgz/untgz.c +// - https://en.wikipedia.org/wiki/Tar_(computing) +// - https://github.com/euroelessar/cutereader/blob/master/karchive/src/ktar.cpp + +#define BLOCKSIZE 512 +#define SHORTNAMESIZE 100 + +enum class TypeFlag : char { + Regular = '0', // regular file + ARegular = 0, // regular file + Link = '1', // link + Symlink = '2', // reserved + Character = '3', // character special + Block = '4', // block special + Directory = '5', // directory + FIFO = '6', // FIFO special + Contiguous = '7', // reserved + // Posix stuff + GlobalPosixHeader = 'g', + ExtendedPosixHeader = 'x', + // 'A'– 'Z' Vendor specific extensions(POSIX .1 - 1988) + // GNU + GNULongLink = 'K', /* long link name */ + GNULongName = 'L', /* long file name */ +}; + +struct Header { /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 */ + char uid[8]; /* 108 */ + char gid[8]; /* 116 */ + char size[12]; /* 124 */ + char mtime[12]; /* 136 */ + char chksum[8]; /* 148 */ + TypeFlag typeflag; /* 156 */ + char linkname[100]; /* 157 */ + char magic[6]; /* 257 */ + char version[2]; /* 263 */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char prefix[155]; /* 345 */ + /* 500 */ +}; + +union Buffer { + char buffer[BLOCKSIZE]; + struct Header header; +}; + +bool readLonglink(QIODevice* in, Buffer buffer, QByteArray& longlink) +{ + qint64 n = 0; + qint64 size = strtoll(buffer.header.size, NULL, 8); + size--; // ignore trailing null + if (errno == ERANGE) { + qCritical() << "The filename size can't be read"; + return false; + } + if (size < 0) { + qCritical() << "The filename size is negative"; + return false; + } + longlink.resize(size + (BLOCKSIZE - size % BLOCKSIZE)); // make the size divisible by BLOCKSIZE + for (qint64 offset = 0; offset < longlink.size(); offset += BLOCKSIZE) { + n = in->read(longlink.data() + offset, BLOCKSIZE); + if (n != BLOCKSIZE) { + qCritical() << "The expected blocksize was not respected for the name"; + return false; + } + } + longlink.truncate(qstrlen(longlink.constData())); + return true; +} + +bool Tar::extract(QIODevice* in, QString dst) +{ + Buffer buffer; + QString name, symlink, firstFolderName; + bool doNotReset = false; + while (true) { + auto n = in->read(buffer.buffer, BLOCKSIZE); + if (n != BLOCKSIZE) { // allways expect complete blocks + qCritical() << "The expected blocksize was not respected"; + return false; + } + if (buffer.header.name[0] == 0) { // end of archive + return true; + } + int mode = strtol(buffer.header.mode, NULL, 8) | QFile::ReadUser | QFile::WriteUser; // hack to ensure write and read permisions + if (errno == ERANGE) { + qCritical() << "The file mode can't be read"; + return false; + } + // there are names that are exactly 100 bytes long + // and neither longlink nor \0 terminated (bug:101472) + if (name.isEmpty()) { + name = QFile::decodeName(QByteArray(buffer.header.name, qstrnlen(buffer.header.name, 100))); + if (!firstFolderName.isEmpty() && name.startsWith(firstFolderName)) { + name = name.mid(firstFolderName.size()); + } + } + if (symlink.isEmpty()) + symlink = QFile::decodeName(QByteArray(buffer.header.linkname, qstrnlen(buffer.header.linkname, 100))); + switch (buffer.header.typeflag) { + case TypeFlag::Regular: + /* fallthrough */ + case TypeFlag::ARegular: { + auto fileName = FS::PathCombine(dst, name); + if (!FS::ensureFilePathExists(fileName)) { + qCritical() << "Can't ensure the file path to exist: " << fileName; + return false; + } + QFile out(fileName); + if (!out.open(QFile::WriteOnly, QFile::Permission(mode))) { + qCritical() << "Can't open file:" << fileName; + return false; + } + qint64 size = strtoll(buffer.header.size, NULL, 8); + if (errno == ERANGE) { + qCritical() << "The file size can't be read"; + return false; + } + while (size > 0) { + QByteArray tmp(BLOCKSIZE, 0); + n = in->read(tmp.data(), BLOCKSIZE); + if (n != BLOCKSIZE) { + qCritical() << "The expected blocksize was not respected when reading file"; + return false; + } + tmp.truncate(qMin(BLOCKSIZE, size)); + out.write(tmp); + size -= BLOCKSIZE; + } + QFile::setPermissions(fileName, QFile::Permissions(mode)); + break; + } + case TypeFlag::Directory: { + if (firstFolderName.isEmpty()) { + firstFolderName = name; + break; + } + auto folderPath = FS::PathCombine(dst, name); + if (!FS::ensureFolderPathExists(folderPath)) { + qCritical() << "Can't ensure that folder exists: " << folderPath; + return false; + } + break; + } + case TypeFlag::GNULongLink: { + doNotReset = true; + QByteArray longlink; + if (readLonglink(in, buffer, longlink)) { + symlink = QFile::decodeName(longlink.constData()); + } else { + qCritical() << "Failed to read long link"; + return false; + } + break; + } + case TypeFlag::GNULongName: { + doNotReset = true; + QByteArray longlink; + if (readLonglink(in, buffer, longlink)) { + name = QFile::decodeName(longlink.constData()); + } else { + qCritical() << "Failed to read long name"; + return false; + } + break; + } + case TypeFlag::Link: + /* fallthrough */ + case TypeFlag::Symlink: { + auto fileName = FS::PathCombine(dst, name); + if (!FS::create_link(FS::PathCombine(QFileInfo(fileName).path(), symlink), fileName)()) { // do not use symlinks + qCritical() << "Can't create link for:" << fileName << " to:" << FS::PathCombine(QFileInfo(fileName).path(), symlink); + return false; + } + FS::ensureFilePathExists(fileName); + QFile::setPermissions(fileName, QFile::Permissions(mode)); + break; + } + case TypeFlag::Character: + /* fallthrough */ + case TypeFlag::Block: + /* fallthrough */ + case TypeFlag::FIFO: + /* fallthrough */ + case TypeFlag::Contiguous: + /* fallthrough */ + case TypeFlag::GlobalPosixHeader: + /* fallthrough */ + case TypeFlag::ExtendedPosixHeader: + /* fallthrough */ + default: + break; + } + if (!doNotReset) { + name.truncate(0); + symlink.truncate(0); + } + doNotReset = false; + } + return true; +} + +bool GZTar::extract(QString src, QString dst) +{ + QuaGzipFile a(src); + if (!a.open(QIODevice::ReadOnly)) { + qCritical() << "Can't open tar file:" << src; + return false; + } + return Tar::extract(&a, dst); +} \ No newline at end of file diff --git a/launcher/Untar.h b/launcher/Untar.h new file mode 100644 index 000000000..54010e085 --- /dev/null +++ b/launcher/Untar.h @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023-2024 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + */ +#pragma once +#include + +// this is a hack used for the java downloader (feel free to remove it in favor of a library) +// both extract functions will extract the first folder inside dest(disregarding the prefix) +namespace Tar { +bool extract(QIODevice* in, QString dst); +}; + +namespace GZTar { +bool extract(QString src, QString dst); +}; \ No newline at end of file diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 070e952a4..62cf4c221 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -120,6 +120,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("Path"); case JavaName: return tr("Java Name"); + case JavaMajor: + return tr("Major"); case Time: return tr("Released"); } @@ -139,6 +141,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return tr("Filesystem path to this version"); case JavaName: return tr("The alternative name of the java version"); + case JavaMajor: + return tr("The java major version"); case Time: return tr("Release date of this version"); } @@ -175,6 +179,8 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const return sourceModel()->data(parentIndex, BaseVersionList::PathRole); case JavaName: return sourceModel()->data(parentIndex, BaseVersionList::JavaNameRole); + case JavaMajor: + return sourceModel()->data(parentIndex, BaseVersionList::JavaMajorRole); case Time: return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate(); default: @@ -323,6 +329,9 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw) if (roles.contains(BaseVersionList::JavaNameRole)) { m_columns.push_back(JavaName); } + if (roles.contains(BaseVersionList::JavaMajorRole)) { + m_columns.push_back(JavaMajor); + } if (roles.contains(Meta::VersionList::TimeRole)) { m_columns.push_back(Time); } diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index cb55b7f14..8aea25795 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -9,7 +9,7 @@ class VersionFilterModel; class VersionProxyModel : public QAbstractProxyModel { Q_OBJECT public: - enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName }; + enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName, JavaMajor }; using FilterMap = QHash>; public: diff --git a/launcher/java/download/ArchiveDownloadTask.cpp b/launcher/java/download/ArchiveDownloadTask.cpp index d62d4d8e2..358860610 100644 --- a/launcher/java/download/ArchiveDownloadTask.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -21,6 +21,7 @@ #include "MMCZip.h" #include "Application.h" +#include "Untar.h" #include "net/ChecksumValidator.h" #include "net/NetJob.h" #include "tasks/Task.h" @@ -69,6 +70,28 @@ void ArchiveDownloadTask::executeTask() void ArchiveDownloadTask::extractJava(QString input) { setStatus(tr("Extracting java")); + if (input.endsWith("tar")) { + setStatus(tr("Extracting java(the progress will not be reported for tar)")); + QFile in(input); + if (!in.open(QFile::ReadOnly)) { + emitFailed(tr("Unable to open supplied tar file.")); + return; + } + if (!Tar::extract(&in, QDir(m_final_path).absolutePath())) { + emitFailed(tr("Unable to extract supplied tar file.")); + return; + } + emitSucceeded(); + return; + } else if (input.endsWith("tar.gz") || input.endsWith("taz") || input.endsWith("tgz")) { + setStatus(tr("Extracting java(the progress will not be reported for tar)")); + if (!GZTar::extract(input, QDir(m_final_path).absolutePath())) { + emitFailed(tr("Unable to extract supplied tar file.")); + return; + } + emitSucceeded(); + return; + } auto zip = std::make_shared(input); if (!zip->open(QuaZip::mdUnzip)) { emitFailed(tr("Unable to open supplied zip file.")); diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index 76b914b6a..66412d6a4 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -92,6 +92,13 @@ QVariant VersionList::data(const QModelIndex& index, int role) const return QVariant::fromValue(version); case RecommendedRole: return version->isRecommended(); + case JavaMajorRole: { + auto major = version->version(); + if (major.startsWith("java")) { + major = "Java " + major.mid(4); + } + return major; + } // FIXME: this should be determined in whatever view/proxy is used... // case LatestRole: return version == getLatestStable(); default: diff --git a/launcher/minecraft/launch/VerifyJavaInstall.cpp b/launcher/minecraft/launch/VerifyJavaInstall.cpp index f26b850eb..5f8b35b02 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.cpp +++ b/launcher/minecraft/launch/VerifyJavaInstall.cpp @@ -54,7 +54,6 @@ void VerifyJavaInstall::executeTask() auto javaArchitecture = settings->get("JavaArchitecture").toString(); auto maxMemAlloc = settings->get("MaxMemAlloc").toInt(); - emit logLine(tr("Java architecture is x%1.").arg(javaArchitecture), MessageLevel::Info); if (javaArchitecture == "32" && maxMemAlloc > 2048) { emit logLine(tr("Max memory allocation exceeds the supported value.\n" "The selected java is 32-bit and doesn't support more than 2048MiB of RAM.\n" diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index 874fc9133..78de3e20a 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -19,16 +19,19 @@ #include "InstallJavaDialog.h" #include +#include #include #include #include #include "Application.h" +#include "BaseVersionList.h" #include "FileSystem.h" #include "java/download/ArchiveDownloadTask.h" #include "java/download/ManifestDownloadTask.h" #include "meta/Index.h" #include "meta/VersionList.h" +#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" #include "ui/java/VersionList.h" #include "ui/widgets/PageContainer.h" @@ -71,8 +74,7 @@ class InstallJavaPage : public QWidget, public BasePage { //! loads the list if needed. void initialize(Meta::VersionList::Ptr vlist) { - vlist->setProvidedRoles({ BaseVersionList::VersionRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole }); - vlist->sort(1); + vlist->setProvidedRoles({ BaseVersionList::JavaMajorRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole }); majorVersionSelect->initialize(vlist.get()); } @@ -219,7 +221,11 @@ void InstallDialog::done(int result) break; } auto deletePath = [final_path] { FS::deletePath(final_path); }; - connect(task.get(), &Task::failed, this, deletePath); + connect(task.get(), &Task::failed, this, [this, &deletePath](QString reason) { + QString error = QString("Java download failed: %1").arg(reason); + CustomMessageBox::selectable(this, tr("Error"), error, QMessageBox::Warning)->show(); + deletePath(); + }); connect(task.get(), &Task::aborted, this, deletePath); ProgressDialog pg(this); pg.setSkipButton(true, tr("Abort")); diff --git a/launcher/ui/java/VersionList.cpp b/launcher/ui/java/VersionList.cpp index 78448ddaf..5e385604d 100644 --- a/launcher/ui/java/VersionList.cpp +++ b/launcher/ui/java/VersionList.cpp @@ -78,6 +78,13 @@ QVariant VersionList::data(const QModelIndex& index, int role) const return false; // do not recommend any version case JavaNameRole: return version->name(); + case JavaMajorRole: { + auto major = version->version.toString(); + if (major.startsWith("java")) { + major = "Java " + major.mid(4); + } + return major; + } case TypeRole: return version->packageType; case Meta::VersionList::TimeRole: diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index e2e498067..1645f2b5f 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -180,7 +180,7 @@ void JavaSettingsWidget::initialize() tr("%1 can automatically download the correct Java version for each version of Minecraft..\n" "Do you want to enable Java auto-download?\n") .arg(BuildConfig.LAUNCHER_DISPLAYNAME), - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) + QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) ->exec(); if (button == QMessageBox::Yes) { m_autodetectJavaCheckBox->setChecked(true); From 3046822272ee97a831667db1c8a222eb304c259e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 21 Mar 2024 19:53:52 +0200 Subject: [PATCH 062/120] Fixed buid Signed-off-by: Trial97 --- launcher/Untar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/Untar.cpp b/launcher/Untar.cpp index 521c504a6..b2f05038c 100644 --- a/launcher/Untar.cpp +++ b/launcher/Untar.cpp @@ -158,10 +158,11 @@ bool Tar::extract(QIODevice* in, QString dst) return false; } QFile out(fileName); - if (!out.open(QFile::WriteOnly, QFile::Permission(mode))) { + if (!out.open(QFile::WriteOnly)) { qCritical() << "Can't open file:" << fileName; return false; } + out.setPermissions(QFile::Permissions(mode)); qint64 size = strtoll(buffer.header.size, NULL, 8); if (errno == ERANGE) { qCritical() << "The file size can't be read"; @@ -178,7 +179,6 @@ bool Tar::extract(QIODevice* in, QString dst) out.write(tmp); size -= BLOCKSIZE; } - QFile::setPermissions(fileName, QFile::Permissions(mode)); break; } case TypeFlag::Directory: { From a7029a9e53cd3d9a2371cd26c257beb898251667 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 21 Mar 2024 20:01:40 +0200 Subject: [PATCH 063/120] Fixed qMin Signed-off-by: Trial97 --- launcher/Untar.cpp | 2 +- launcher/Untar.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/Untar.cpp b/launcher/Untar.cpp index b2f05038c..bae6c5d17 100644 --- a/launcher/Untar.cpp +++ b/launcher/Untar.cpp @@ -175,7 +175,7 @@ bool Tar::extract(QIODevice* in, QString dst) qCritical() << "The expected blocksize was not respected when reading file"; return false; } - tmp.truncate(qMin(BLOCKSIZE, size)); + tmp.truncate(qMin(qint64(BLOCKSIZE), size)); out.write(tmp); size -= BLOCKSIZE; } diff --git a/launcher/Untar.h b/launcher/Untar.h index 54010e085..50e3a16e3 100644 --- a/launcher/Untar.h +++ b/launcher/Untar.h @@ -39,8 +39,8 @@ // both extract functions will extract the first folder inside dest(disregarding the prefix) namespace Tar { bool extract(QIODevice* in, QString dst); -}; +} namespace GZTar { bool extract(QString src, QString dst); -}; \ No newline at end of file +} \ No newline at end of file From 0b87e4c03b55c96966255eb8440b0c4e7b182c63 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 22 Mar 2024 12:29:15 +0200 Subject: [PATCH 064/120] Fiexed codeql warning Signed-off-by: Trial97 --- launcher/Untar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/Untar.cpp b/launcher/Untar.cpp index bae6c5d17..1d11dfd60 100644 --- a/launcher/Untar.cpp +++ b/launcher/Untar.cpp @@ -94,7 +94,7 @@ union Buffer { struct Header header; }; -bool readLonglink(QIODevice* in, Buffer buffer, QByteArray& longlink) +bool readLonglink(QIODevice* in, Buffer& buffer, QByteArray& longlink) { qint64 n = 0; qint64 size = strtoll(buffer.header.size, NULL, 8); From c0754b80a2b8612ce2874888c0f40b41b2eac765 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 22 Mar 2024 22:17:58 +0200 Subject: [PATCH 065/120] Add resize to last column Signed-off-by: Trial97 --- launcher/ui/pages/global/JavaPage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 6d8b95c24..fda4f8705 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -65,6 +65,7 @@ JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { ui->managedJavaList->initialize(new JavaInstallList(this, true)); + ui->managedJavaList->setResizeOn(2); ui->managedJavaList->selectCurrent(); ui->managedJavaList->setEmptyString(tr("No managed java versions are installed")); ui->managedJavaList->setEmptyErrorString(tr("Couldn't load the managed java list!")); From 93f6315b16de3b2170d0263d7befcac5dcfaa01d Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Wed, 27 Mar 2024 19:34:04 +0200 Subject: [PATCH 066/120] Update CMakeLists.txt Co-authored-by: seth Signed-off-by: Alexandru Ionut Tripon --- CMakeLists.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 40ccff595..f4298aedb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,7 +220,17 @@ set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build against") # Java downloader -option(ENABLE_JAVA_DOWNLOADER "Build the java downloader feature" ON) +set(ENABLE_JAVA_DOWNLOADER_DEFAULT ON) + +# Although we recommend enabling this, we cannot guarantee binary compatibility on +# differing Linux/BSD/etc distributions. Downstream packagers should be explicitly opt-ing into this +# feature if they know it will work with their distribution. +if(UNIX AND NOT APPLE) + set(ENABLE_JAVA_DOWNLOADER_DEFAULT OFF) +endif() + +# Java downloader +option(ENABLE_JAVA_DOWNLOADER "Build the java downloader feature" ${ENABLE_JAVA_DOWNLOADER_DEFAULT}) # Native libraries if(UNIX AND APPLE) From 45028ddc6142b019d28dadd31b8c87433adea312 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 28 Mar 2024 14:58:05 +0200 Subject: [PATCH 067/120] Added java downloader to CI build Signed-off-by: Trial97 --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9cb737df6..500aca5cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -274,23 +274,23 @@ jobs: - name: Configure CMake (macOS) if: runner.os == 'macOS' && matrix.qt_ver == 6 run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -G Ninja - name: Configure CMake (macOS-Legacy) if: runner.os == 'macOS' && matrix.qt_ver == 5 run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja - name: Configure CMake (Windows MinGW-w64) if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja - name: Configure CMake (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} # https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix) if ("${{ env.CCACHE_VAR }}") { @@ -305,7 +305,7 @@ jobs: - name: Configure CMake (Linux) if: runner.os == 'Linux' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -G Ninja ## # BUILD From 81874f22f74e3d254e16c3054abb28881b50d01a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 29 Mar 2024 00:10:59 +0200 Subject: [PATCH 068/120] Fixed tar extract Signed-off-by: Trial97 --- launcher/Untar.cpp | 96 +++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/launcher/Untar.cpp b/launcher/Untar.cpp index 1d11dfd60..f1963e7aa 100644 --- a/launcher/Untar.cpp +++ b/launcher/Untar.cpp @@ -33,13 +33,11 @@ * limitations under the License. */ #include "Untar.h" -#include -#include #include #include +#include #include #include -#include #include "FileSystem.h" // adaptation of the: @@ -69,40 +67,30 @@ enum class TypeFlag : char { GNULongName = 'L', /* long file name */ }; -struct Header { /* byte offset */ - char name[100]; /* 0 */ - char mode[8]; /* 100 */ - char uid[8]; /* 108 */ - char gid[8]; /* 116 */ - char size[12]; /* 124 */ - char mtime[12]; /* 136 */ - char chksum[8]; /* 148 */ - TypeFlag typeflag; /* 156 */ - char linkname[100]; /* 157 */ - char magic[6]; /* 257 */ - char version[2]; /* 263 */ - char uname[32]; /* 265 */ - char gname[32]; /* 297 */ - char devmajor[8]; /* 329 */ - char devminor[8]; /* 337 */ - char prefix[155]; /* 345 */ - /* 500 */ -}; +// struct Header { /* byte offset */ +// char name[100]; /* 0 */ +// char mode[8]; /* 100 */ +// char uid[8]; /* 108 */ +// char gid[8]; /* 116 */ +// char size[12]; /* 124 */ +// char mtime[12]; /* 136 */ +// char chksum[8]; /* 148 */ +// TypeFlag typeflag; /* 156 */ +// char linkname[100]; /* 157 */ +// char magic[6]; /* 257 */ +// char version[2]; /* 263 */ +// char uname[32]; /* 265 */ +// char gname[32]; /* 297 */ +// char devmajor[8]; /* 329 */ +// char devminor[8]; /* 337 */ +// char prefix[155]; /* 345 */ +// /* 500 */ +// }; -union Buffer { - char buffer[BLOCKSIZE]; - struct Header header; -}; - -bool readLonglink(QIODevice* in, Buffer& buffer, QByteArray& longlink) +bool readLonglink(QIODevice* in, qint64 size, QByteArray& longlink) { qint64 n = 0; - qint64 size = strtoll(buffer.header.size, NULL, 8); size--; // ignore trailing null - if (errno == ERANGE) { - qCritical() << "The filename size can't be read"; - return false; - } if (size < 0) { qCritical() << "The filename size is negative"; return false; @@ -119,36 +107,51 @@ bool readLonglink(QIODevice* in, Buffer& buffer, QByteArray& longlink) return true; } +int getOctal(char* buffer, int maxlenght, bool* ok) +{ + return QByteArray(buffer, qstrnlen(buffer, maxlenght)).toInt(ok, 8); +} + +QString decodeName(char* name) +{ + return QFile::decodeName(QByteArray(name, qstrnlen(name, 100))); +} bool Tar::extract(QIODevice* in, QString dst) { - Buffer buffer; + char buffer[BLOCKSIZE]; QString name, symlink, firstFolderName; - bool doNotReset = false; + bool doNotReset = false, ok; while (true) { - auto n = in->read(buffer.buffer, BLOCKSIZE); + auto n = in->read(buffer, BLOCKSIZE); if (n != BLOCKSIZE) { // allways expect complete blocks qCritical() << "The expected blocksize was not respected"; return false; } - if (buffer.header.name[0] == 0) { // end of archive + if (buffer[0] == 0) { // end of archive return true; } - int mode = strtol(buffer.header.mode, NULL, 8) | QFile::ReadUser | QFile::WriteUser; // hack to ensure write and read permisions - if (errno == ERANGE) { + int mode = getOctal(buffer + 100, 8, &ok) | QFile::ReadUser | QFile::WriteUser; // hack to ensure write and read permisions + if (!ok) { qCritical() << "The file mode can't be read"; return false; } // there are names that are exactly 100 bytes long // and neither longlink nor \0 terminated (bug:101472) + if (name.isEmpty()) { - name = QFile::decodeName(QByteArray(buffer.header.name, qstrnlen(buffer.header.name, 100))); + name = decodeName(buffer); if (!firstFolderName.isEmpty() && name.startsWith(firstFolderName)) { name = name.mid(firstFolderName.size()); } } if (symlink.isEmpty()) - symlink = QFile::decodeName(QByteArray(buffer.header.linkname, qstrnlen(buffer.header.linkname, 100))); - switch (buffer.header.typeflag) { + symlink = decodeName(buffer); + qint64 size = getOctal(buffer + 124, 12, &ok); + if (!ok) { + qCritical() << "The file size can't be read"; + return false; + } + switch (TypeFlag(buffer[156])) { case TypeFlag::Regular: /* fallthrough */ case TypeFlag::ARegular: { @@ -163,11 +166,6 @@ bool Tar::extract(QIODevice* in, QString dst) return false; } out.setPermissions(QFile::Permissions(mode)); - qint64 size = strtoll(buffer.header.size, NULL, 8); - if (errno == ERANGE) { - qCritical() << "The file size can't be read"; - return false; - } while (size > 0) { QByteArray tmp(BLOCKSIZE, 0); n = in->read(tmp.data(), BLOCKSIZE); @@ -196,7 +194,7 @@ bool Tar::extract(QIODevice* in, QString dst) case TypeFlag::GNULongLink: { doNotReset = true; QByteArray longlink; - if (readLonglink(in, buffer, longlink)) { + if (readLonglink(in, size, longlink)) { symlink = QFile::decodeName(longlink.constData()); } else { qCritical() << "Failed to read long link"; @@ -207,7 +205,7 @@ bool Tar::extract(QIODevice* in, QString dst) case TypeFlag::GNULongName: { doNotReset = true; QByteArray longlink; - if (readLonglink(in, buffer, longlink)) { + if (readLonglink(in, size, longlink)) { name = QFile::decodeName(longlink.constData()); } else { qCritical() << "Failed to read long name"; From b23b53d98d5c99353a79355371a7eb7a8537df0c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 18 May 2024 14:43:58 +0300 Subject: [PATCH 069/120] Add missing header Signed-off-by: Trial97 --- launcher/java/JavaChecker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index 678c98cd4..c54a5b04b 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -41,6 +41,7 @@ #include #include "Commandline.h" +#include "FileSystem.h" #include "java/JavaUtils.h" JavaChecker::JavaChecker(QString path, QString args, int minMem, int maxMem, int permGen, int id, QObject* parent) From abb628edb36a7e3e433dee93a224dbd4329acc24 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 20 May 2024 18:23:43 +0300 Subject: [PATCH 070/120] remove OverrideJava Signed-off-by: Trial97 --- launcher/launch/steps/CheckJava.cpp | 2 +- launcher/minecraft/MinecraftInstance.cpp | 21 +++++++------------ launcher/minecraft/launch/AutoInstallJava.cpp | 4 +--- .../pages/instance/InstanceSettingsPage.cpp | 8 ++----- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/launcher/launch/steps/CheckJava.cpp b/launcher/launch/steps/CheckJava.cpp index a8c7305ab..b5b85563a 100644 --- a/launcher/launch/steps/CheckJava.cpp +++ b/launcher/launch/steps/CheckJava.cpp @@ -47,7 +47,7 @@ void CheckJava::executeTask() auto instance = m_parent->instance(); auto settings = instance->settings(); m_javaPath = FS::ResolveExecutable(settings->get("JavaPath").toString()); - bool perInstance = settings->get("OverrideJava").toBool() || settings->get("OverrideJavaLocation").toBool(); + bool perInstance = settings->get("OverrideJavaLocation").toBool(); auto realJavaPath = QStandardPaths::findExecutable(m_javaPath); if (realJavaPath.isEmpty()) { diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 9fa313843..0b0a279a5 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -136,25 +136,20 @@ void MinecraftInstance::loadSpecificSettings() return; // Java Settings - auto javaOverride = m_settings->registerSetting("OverrideJava", false); auto locationOverride = m_settings->registerSetting("OverrideJavaLocation", false); auto argsOverride = m_settings->registerSetting("OverrideJavaArgs", false); - // combinations - auto javaOrLocation = std::make_shared("JavaOrLocationOverride", javaOverride, locationOverride); - auto javaOrArgs = std::make_shared("JavaOrArgsOverride", javaOverride, argsOverride); - if (auto global_settings = globalSettings()) { - m_settings->registerOverride(global_settings->getSetting("JavaPath"), javaOrLocation); - m_settings->registerOverride(global_settings->getSetting("JvmArgs"), javaOrArgs); - m_settings->registerOverride(global_settings->getSetting("IgnoreJavaCompatibility"), javaOrLocation); + m_settings->registerOverride(global_settings->getSetting("JavaPath"), locationOverride); + m_settings->registerOverride(global_settings->getSetting("JvmArgs"), argsOverride); + m_settings->registerOverride(global_settings->getSetting("IgnoreJavaCompatibility"), locationOverride); // special! - m_settings->registerPassthrough(global_settings->getSetting("JavaSignature"), javaOrLocation); - m_settings->registerPassthrough(global_settings->getSetting("JavaArchitecture"), javaOrLocation); - m_settings->registerPassthrough(global_settings->getSetting("JavaRealArchitecture"), javaOrLocation); - m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), javaOrLocation); - m_settings->registerPassthrough(global_settings->getSetting("JavaVendor"), javaOrLocation); + m_settings->registerPassthrough(global_settings->getSetting("JavaSignature"), locationOverride); + m_settings->registerPassthrough(global_settings->getSetting("JavaArchitecture"), locationOverride); + m_settings->registerPassthrough(global_settings->getSetting("JavaRealArchitecture"), locationOverride); + m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), locationOverride); + m_settings->registerPassthrough(global_settings->getSetting("JavaVendor"), locationOverride); // Window Size auto windowSetting = m_settings->registerSetting("OverrideWindow", false); diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index 1dc91003f..95bfa1dec 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -61,8 +61,7 @@ void AutoInstallJava::executeTask() { auto settings = m_instance->settings(); if (!APPLICATION->settings()->get("AutomaticJavaSwitch").toBool() || - (settings->get("OverrideJava").toBool() && settings->get("OverrideJavaLocation").toBool() && - QFileInfo::exists(settings->get("JavaPath").toString()))) { + (settings->get("OverrideJavaLocation").toBool() && QFileInfo::exists(settings->get("JavaPath").toString()))) { emitSucceeded(); return; } @@ -126,7 +125,6 @@ void AutoInstallJava::executeTask() void AutoInstallJava::setJavaPath(QString path) { auto settings = m_instance->settings(); - settings->set("OverrideJava", true); settings->set("OverrideJavaLocation", true); settings->set("JavaPath", path); emit logLine(tr("Compatible java found at: %1.").arg(path), MessageLevel::Info); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index c248a47f7..fa52f2c51 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -190,9 +190,6 @@ void InstanceSettingsPage::applySettings() m_settings->reset("JvmArgs"); } - // old generic 'override both' is removed. - m_settings->reset("OverrideJava"); - // Custom Commands bool custcmd = ui->customCommands->checked(); m_settings->set("OverrideCommands", custcmd); @@ -321,9 +318,8 @@ void InstanceSettingsPage::loadSettings() ui->labelPermgenNote->setVisible(permGenVisible); // Java Settings - bool overrideJava = m_settings->get("OverrideJava").toBool(); - bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool() || overrideJava; - bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool() || overrideJava; + bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool(); + bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool(); ui->javaSettingsGroupBox->setChecked(overrideLocation); ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString()); From 0e239dfb2a85c947d656764fa0036965eb040b40 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 20 May 2024 18:24:19 +0300 Subject: [PATCH 071/120] fix crash on first display with java downloader off Signed-off-by: Trial97 --- launcher/ui/setupwizard/JavaWizardPage.cpp | 8 +--- launcher/ui/widgets/JavaSettingsWidget.cpp | 49 ++++++++++++---------- launcher/ui/widgets/JavaSettingsWidget.h | 4 +- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/launcher/ui/setupwizard/JavaWizardPage.cpp b/launcher/ui/setupwizard/JavaWizardPage.cpp index d537580fc..a47cebcaa 100644 --- a/launcher/ui/setupwizard/JavaWizardPage.cpp +++ b/launcher/ui/setupwizard/JavaWizardPage.cpp @@ -12,12 +12,8 @@ #include -#include "FileSystem.h" #include "JavaCommon.h" -#include "java/JavaInstall.h" -#include "java/JavaUtils.h" -#include "ui/dialogs/CustomMessageBox.h" #include "ui/widgets/JavaSettingsWidget.h" #include "ui/widgets/VersionSelectWidget.h" @@ -57,8 +53,8 @@ bool JavaWizardPage::validatePage() { auto settings = APPLICATION->settings(); auto result = m_java_widget->validate(); - settings->set("AutomaticJavaSwitch", m_java_widget->autodetectJava()); - settings->set("AutomaticJavaDownload", m_java_widget->autodownloadJava()); + settings->set("AutomaticJavaSwitch", m_java_widget->autoDetectJava()); + settings->set("AutomaticJavaDownload", m_java_widget->autoDownloadJava()); switch (result) { default: case JavaSettingsWidget::ValidationStatus::Bad: { diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 1645f2b5f..34cd70f35 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -43,7 +43,9 @@ JavaSettingsWidget::JavaSettingsWidget(QWidget* parent) : QWidget(parent) connect(m_javaBrowseBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaBrowseBtn_clicked); connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaSettingsWidget::javaPathEdited); connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaSettingsWidget::on_javaStatusBtn_clicked); - connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaDownloadBtn_clicked); + if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { + connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaDownloadBtn_clicked); + } } void JavaSettingsWidget::setupUi() @@ -176,18 +178,21 @@ void JavaSettingsWidget::initialize() m_permGenSpinBox->setValue(observedPermGenMemory); updateThresholds(); - auto button = CustomMessageBox::selectable(this, tr("Auto Java Download"), - tr("%1 can automatically download the correct Java version for each version of Minecraft..\n" - "Do you want to enable Java auto-download?\n") - .arg(BuildConfig.LAUNCHER_DISPLAYNAME), - QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) - ->exec(); - if (button == QMessageBox::Yes) { - m_autodetectJavaCheckBox->setChecked(true); - m_autodownloadCheckBox->setChecked(true); - } else { - m_autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); - m_autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool()); + if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { + auto button = + CustomMessageBox::selectable(this, tr("Auto Java Download"), + tr("%1 can automatically download the correct Java version for each version of Minecraft..\n" + "Do you want to enable Java auto-download?\n") + .arg(BuildConfig.LAUNCHER_DISPLAYNAME), + QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) + ->exec(); + if (button == QMessageBox::Yes) { + m_autodetectJavaCheckBox->setChecked(true); + m_autodownloadCheckBox->setChecked(true); + } else { + m_autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); + m_autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool()); + } } } @@ -211,7 +216,7 @@ JavaSettingsWidget::ValidationStatus JavaSettingsWidget::validate() case JavaStatus::DoesNotStart: /* fallthrough */ case JavaStatus::ReturnedInvalidData: { - if (!m_autodownloadCheckBox->isChecked()) { // the java will not be autodownloaded + if (!(BuildConfig.JAVA_DOWNLOADER_ENABLED && m_autodownloadCheckBox->isChecked())) { // the java will not be autodownloaded int button = QMessageBox::No; if (m_result.mojangPlatform == "32" && maxHeapSize() > 2048) { button = CustomMessageBox::selectable( @@ -488,7 +493,9 @@ void JavaSettingsWidget::retranslate() m_minMemSpinBox->setToolTip(tr("The amount of memory Minecraft is started with.")); m_permGenSpinBox->setToolTip(tr("The amount of memory available to store loaded Java classes.")); m_javaBrowseBtn->setText(tr("Browse")); - m_autodownloadCheckBox->setText(tr("Auto-download Mojang Java")); + if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { + m_autodownloadCheckBox->setText(tr("Auto-download Mojang Java")); + } m_autodetectJavaCheckBox->setText(tr("Autodetect Java version")); m_autoJavaGroupBox->setTitle(tr("Autodetect Java")); } @@ -522,12 +529,12 @@ void JavaSettingsWidget::updateThresholds() } } -bool JavaSettingsWidget::autodownloadJava() const +bool JavaSettingsWidget::autoDownloadJava() const +{ + return m_autodownloadCheckBox && m_autodownloadCheckBox->isChecked(); +} + +bool JavaSettingsWidget::autoDetectJava() const { return m_autodetectJavaCheckBox->isChecked(); } - -bool JavaSettingsWidget::autodetectJava() const -{ - return m_autodownloadCheckBox->isChecked(); -} diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index c8b6953df..877e60f46 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -42,8 +42,8 @@ class JavaSettingsWidget : public QWidget { int minHeapSize() const; int maxHeapSize() const; QString javaPath() const; - bool autodetectJava() const; - bool autodownloadJava() const; + bool autoDetectJava() const; + bool autoDownloadJava() const; void updateThresholds(); From 7a42fb284a28657106bf189a5ead0b1add38e9c8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 20 May 2024 18:33:40 +0300 Subject: [PATCH 072/120] reverse java version Signed-off-by: Trial97 --- launcher/ui/java/VersionList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/java/VersionList.cpp b/launcher/ui/java/VersionList.cpp index 5e385604d..6f60a6867 100644 --- a/launcher/ui/java/VersionList.cpp +++ b/launcher/ui/java/VersionList.cpp @@ -103,7 +103,7 @@ bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right) { auto rleft = std::dynamic_pointer_cast(right); auto rright = std::dynamic_pointer_cast(left); - return (*rleft) > (*rright); + return (*rleft) < (*rright); } void VersionList::sortVersions() From f6a7fc215aaacc235842a8f3fd31b81e3e9720c9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 21 May 2024 08:33:09 +0300 Subject: [PATCH 073/120] update java sorting by taking into consideration release time Signed-off-by: Trial97 --- launcher/java/JavaMetadata.cpp | 7 +++++++ launcher/java/JavaVersion.cpp | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/launcher/java/JavaMetadata.cpp b/launcher/java/JavaMetadata.cpp index e721947a7..2272470a8 100644 --- a/launcher/java/JavaMetadata.cpp +++ b/launcher/java/JavaMetadata.cpp @@ -83,6 +83,13 @@ bool Metadata::operator<(const Metadata& rhs) if (id > rhs.version) { return false; } + auto date = releaseTime; + if (date < rhs.releaseTime) { + return true; + } + if (date > rhs.releaseTime) { + return false; + } return StringUtils::naturalCompare(m_name, rhs.m_name, Qt::CaseInsensitive) < 0; } diff --git a/launcher/java/JavaVersion.cpp b/launcher/java/JavaVersion.cpp index 2dc23472e..5e9700012 100644 --- a/launcher/java/JavaVersion.cpp +++ b/launcher/java/JavaVersion.cpp @@ -59,12 +59,6 @@ bool JavaVersion::operator<(const JavaVersion& rhs) auto major = m_major; auto rmajor = rhs.m_major; - // HACK: discourage using java 9 - if (major > 8) - major = -major; - if (rmajor > 8) - rmajor = -rmajor; - if (major < rmajor) return true; if (major > rmajor) From bbf52e35497a596121befb4f7d9225ab99251732 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 16 Jun 2024 01:59:50 +0300 Subject: [PATCH 074/120] renamed dialog and button action Signed-off-by: Trial97 --- launcher/ui/java/InstallJavaDialog.cpp | 12 ++++++++---- launcher/ui/pages/global/JavaPage.cpp | 7 +------ launcher/ui/pages/global/JavaPage.h | 1 - launcher/ui/widgets/JavaSettingsWidget.cpp | 4 ++-- launcher/ui/widgets/JavaSettingsWidget.h | 2 +- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index 78de3e20a..60e3a770c 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -184,18 +184,18 @@ InstallDialog::InstallDialog(const QString& uid, QWidget* parent) QList InstallDialog::getPages() { return { - // NeoForge + // Mojang new InstallJavaPage("net.minecraft.java", "", tr("Mojang")), - // Forge + // Adoptium new InstallJavaPage("net.adoptium.java", "", tr("Adoptium")), - // Fabric + // Azul new InstallJavaPage("com.azul.java", "", tr("Azul")), }; } QString InstallDialog::dialogTitle() { - return tr("Install Loader"); + return tr("Install Java"); } void InstallDialog::validate(BasePage* page) @@ -230,7 +230,11 @@ void InstallDialog::done(int result) ProgressDialog pg(this); pg.setSkipButton(true, tr("Abort")); pg.execWithTask(task.get()); + } else { + return; } + } else { + return; } } diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index fda4f8705..c8bbf6361 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -199,7 +199,7 @@ void JavaPage::on_javaTestBtn_clicked() checker->run(); } -void JavaPage::on_javaDownloadBtn_clicked() +void JavaPage::on_downloadJavaButton_clicked() { auto jdialog = new Java::InstallDialog({}, this); jdialog->exec(); @@ -251,11 +251,6 @@ void JavaPage::updateThresholds() } } -void JavaPage::on_downloadJavaButton_clicked() -{ - on_javaDownloadBtn_clicked(); -} - void JavaPage::on_removeJavaButton_clicked() { auto version = ui->managedJavaList->selectedVersion(); diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h index 48e557740..0a1c4a6be 100644 --- a/launcher/ui/pages/global/JavaPage.h +++ b/launcher/ui/pages/global/JavaPage.h @@ -72,7 +72,6 @@ class JavaPage : public QWidget, public BasePage { void on_javaDetectBtn_clicked(); void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); - void on_javaDownloadBtn_clicked(); void on_downloadJavaButton_clicked(); void on_removeJavaButton_clicked(); void on_refreshJavaButton_clicked(); diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 34cd70f35..e16f650fc 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -44,7 +44,7 @@ JavaSettingsWidget::JavaSettingsWidget(QWidget* parent) : QWidget(parent) connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaSettingsWidget::javaPathEdited); connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaSettingsWidget::on_javaStatusBtn_clicked); if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { - connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaSettingsWidget::on_javaDownloadBtn_clicked); + connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaSettingsWidget::javaDownloadBtn_clicked); } } @@ -354,7 +354,7 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked() checkJavaPath(cooked_path); } -void JavaSettingsWidget::on_javaDownloadBtn_clicked() +void JavaSettingsWidget::javaDownloadBtn_clicked() { auto jdialog = new Java::InstallDialog({}, this); jdialog->exec(); diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index 877e60f46..622c473fe 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -53,7 +53,7 @@ class JavaSettingsWidget : public QWidget { void javaVersionSelected(BaseVersion::Ptr version); void on_javaBrowseBtn_clicked(); void on_javaStatusBtn_clicked(); - void on_javaDownloadBtn_clicked(); + void javaDownloadBtn_clicked(); void checkFinished(const JavaChecker::Result& result); protected: /* methods */ From 94fd02a34f1146fa84c6ea2516b694f6e3ce3d91 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 16 Jun 2024 14:26:19 +0300 Subject: [PATCH 075/120] fix java download button Signed-off-by: Trial97 --- launcher/ui/java/InstallJavaDialog.cpp | 19 +++++++++---------- launcher/ui/java/InstallJavaDialog.h | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index 60e3a770c..d92402236 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -60,7 +60,8 @@ class InstallJavaPage : public QWidget, public BasePage { javaVersionSelect->setEmptyErrorString(tr("Couldn't load or download the java version lists!")); horizontalLayout->addWidget(javaVersionSelect, 4); connect(majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::setSelectedVersion); - connect(javaVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectedVersionChanged); + connect(majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectionChanged); + connect(javaVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectionChanged); QMetaObject::connectSlotsByName(this); } @@ -119,7 +120,7 @@ class InstallJavaPage : public QWidget, public BasePage { javaVersionSelect->loadList(); } signals: - void selectedVersionChanged(BaseVersion::Ptr version); + void selectionChanged(); private: const QString uid; @@ -171,14 +172,11 @@ InstallDialog::InstallDialog(const QString& uid, QWidget* parent) if (page->id() == uid) container->selectPage(page->id()); - connect(pageCast(page), &InstallJavaPage::selectedVersionChanged, this, [this, page] { - if (page->id() == container->selectedPage()->id()) - validate(container->selectedPage()); - }); + connect(pageCast(page), &InstallJavaPage::selectionChanged, this, [this] { validate(); }); } - connect(container, &PageContainer::selectedPageChanged, this, [this](BasePage* previous, BasePage* current) { validate(current); }); + connect(container, &PageContainer::selectedPageChanged, this, [this] { validate(); }); pageCast(container->selectedPage())->selectSearch(); - validate(container->selectedPage()); + validate(); } QList InstallDialog::getPages() @@ -198,9 +196,10 @@ QString InstallDialog::dialogTitle() return tr("Install Java"); } -void InstallDialog::validate(BasePage* page) +void InstallDialog::validate() { - buttons->button(QDialogButtonBox::Ok)->setEnabled(pageCast(page)->selectedVersion() != nullptr); + buttons->button(QDialogButtonBox::Ok) + ->setEnabled(!!std::dynamic_pointer_cast(pageCast(container->selectedPage())->selectedVersion())); } void InstallDialog::done(int result) diff --git a/launcher/ui/java/InstallJavaDialog.h b/launcher/ui/java/InstallJavaDialog.h index 525e750aa..80d010c1a 100644 --- a/launcher/ui/java/InstallJavaDialog.h +++ b/launcher/ui/java/InstallJavaDialog.h @@ -36,7 +36,7 @@ class InstallDialog final : public QDialog, private BasePageProvider { QList getPages() override; QString dialogTitle() override; - void validate(BasePage* page); + void validate(); void done(int result) override; private: From 8d3e6667cdb51c4018604313629bd57744bca8aa Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 16 Jun 2024 15:09:49 +0300 Subject: [PATCH 076/120] fix java download tasks Signed-off-by: Trial97 --- .../java/download/ArchiveDownloadTask.cpp | 42 +++++++++--------- launcher/java/download/ArchiveDownloadTask.h | 2 + .../java/download/ManifestDownloadTask.cpp | 44 ++++++++++--------- launcher/java/download/ManifestDownloadTask.h | 2 + 4 files changed, 49 insertions(+), 41 deletions(-) diff --git a/launcher/java/download/ArchiveDownloadTask.cpp b/launcher/java/download/ArchiveDownloadTask.cpp index 358860610..5aed70ede 100644 --- a/launcher/java/download/ArchiveDownloadTask.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -50,21 +50,17 @@ void ArchiveDownloadTask::executeTask() download->addNetAction(action); auto fullPath = entry->getFullPath(); - connect(download.get(), &NetJob::finished, [download, this] { - disconnect(this, &Task::aborted, download.get(), &NetJob::abort); - download->deleteLater(); - }); - connect(download.get(), &NetJob::failed, this, &ArchiveDownloadTask::emitFailed); - connect(this, &Task::aborted, download.get(), &NetJob::abort); + connect(download.get(), &Task::failed, this, &ArchiveDownloadTask::emitFailed); connect(download.get(), &Task::progress, this, &ArchiveDownloadTask::setProgress); connect(download.get(), &Task::stepProgress, this, &ArchiveDownloadTask::propagateStepProgress); connect(download.get(), &Task::status, this, &ArchiveDownloadTask::setStatus); connect(download.get(), &Task::details, this, &ArchiveDownloadTask::setDetails); - connect(download.get(), &NetJob::succeeded, [this, fullPath] { + connect(download.get(), &Task::succeeded, [this, fullPath] { // This should do all of the extracting and creating folders extractJava(fullPath); }); - download->start(); + m_task = download; + m_task->start(); } void ArchiveDownloadTask::extractJava(QString input) @@ -102,34 +98,40 @@ void ArchiveDownloadTask::extractJava(QString input) emitFailed("Empty archive"); return; } - auto zipTask = makeShared(zip, m_final_path, files[0]); + m_task = makeShared(zip, m_final_path, files[0]); auto progressStep = std::make_shared(); - connect(zipTask.get(), &Task::finished, this, [this, progressStep] { + connect(m_task.get(), &Task::finished, this, [this, progressStep] { progressStep->state = TaskStepState::Succeeded; stepProgress(*progressStep); }); - connect(this, &Task::aborted, zipTask.get(), &Task::abort); - connect(zipTask.get(), &Task::finished, [zipTask, this] { disconnect(this, &Task::aborted, zipTask.get(), &Task::abort); }); - - connect(zipTask.get(), &Task::succeeded, this, &ArchiveDownloadTask::emitSucceeded); - connect(zipTask.get(), &Task::aborted, this, &ArchiveDownloadTask::emitAborted); - connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) { + connect(m_task.get(), &Task::succeeded, this, &ArchiveDownloadTask::emitSucceeded); + connect(m_task.get(), &Task::aborted, this, &ArchiveDownloadTask::emitAborted); + connect(m_task.get(), &Task::failed, this, [this, progressStep](QString reason) { progressStep->state = TaskStepState::Failed; stepProgress(*progressStep); emitFailed(reason); }); - connect(zipTask.get(), &Task::stepProgress, this, &ArchiveDownloadTask::propagateStepProgress); + connect(m_task.get(), &Task::stepProgress, this, &ArchiveDownloadTask::propagateStepProgress); - connect(zipTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { + connect(m_task.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { progressStep->update(current, total); stepProgress(*progressStep); }); - connect(zipTask.get(), &Task::status, this, [this, progressStep](QString status) { + connect(m_task.get(), &Task::status, this, [this, progressStep](QString status) { progressStep->status = status; stepProgress(*progressStep); }); - zipTask->start(); + m_task->start(); } + +bool ArchiveDownloadTask::abort() +{ + auto aborted = canAbort(); + if (m_task) + aborted = m_task->abort(); + emitAborted(); + return aborted; +}; } // namespace Java \ No newline at end of file diff --git a/launcher/java/download/ArchiveDownloadTask.h b/launcher/java/download/ArchiveDownloadTask.h index c656567fe..1db33763a 100644 --- a/launcher/java/download/ArchiveDownloadTask.h +++ b/launcher/java/download/ArchiveDownloadTask.h @@ -30,6 +30,7 @@ class ArchiveDownloadTask : public Task { [[nodiscard]] bool canAbort() const override { return true; } void executeTask() override; + virtual bool abort() override; private slots: void extractJava(QString input); @@ -39,5 +40,6 @@ class ArchiveDownloadTask : public Task { QString m_final_path; QString m_checksum_type; QString m_checksum_hash; + Task::Ptr m_task; }; } // namespace Java \ No newline at end of file diff --git a/launcher/java/download/ManifestDownloadTask.cpp b/launcher/java/download/ManifestDownloadTask.cpp index 5551c75d5..1fcc6f172 100644 --- a/launcher/java/download/ManifestDownloadTask.cpp +++ b/launcher/java/download/ManifestDownloadTask.cpp @@ -51,18 +51,13 @@ void ManifestDownloadTask::executeTask() } download->addNetAction(action); - connect(download.get(), &NetJob::finished, [download, this] { - disconnect(this, &Task::aborted, download.get(), &NetJob::abort); - download->deleteLater(); - }); - connect(download.get(), &NetJob::failed, this, &ManifestDownloadTask::emitFailed); - connect(this, &Task::aborted, download.get(), &NetJob::abort); + connect(download.get(), &Task::failed, this, &ManifestDownloadTask::emitFailed); connect(download.get(), &Task::progress, this, &ManifestDownloadTask::setProgress); connect(download.get(), &Task::stepProgress, this, &ManifestDownloadTask::propagateStepProgress); connect(download.get(), &Task::status, this, &ManifestDownloadTask::setStatus); connect(download.get(), &Task::details, this, &ManifestDownloadTask::setDetails); - connect(download.get(), &NetJob::succeeded, [files, this] { + connect(download.get(), &Task::succeeded, [files, this] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -73,7 +68,8 @@ void ManifestDownloadTask::executeTask() } downloadJava(doc); }); - download->start(); + m_task = download; + m_task->start(); } void ManifestDownloadTask::downloadJava(const QJsonDocument& doc) @@ -107,7 +103,7 @@ void ManifestDownloadTask::downloadJava(const QJsonDocument& doc) } } } - auto elementDownload = new NetJob("JRE::FileDownload", APPLICATION->network()); + auto elementDownload = makeShared("JRE::FileDownload", APPLICATION->network()); for (const auto& file : toDownload) { auto dl = Net::Download::makeFile(file.url, file.path); if (!file.hash.isEmpty()) { @@ -119,18 +115,24 @@ void ManifestDownloadTask::downloadJava(const QJsonDocument& doc) } elementDownload->addNetAction(dl); } - connect(elementDownload, &NetJob::finished, [elementDownload, this] { - disconnect(this, &Task::aborted, elementDownload, &NetJob::abort); - elementDownload->deleteLater(); - }); - connect(elementDownload, &NetJob::failed, this, &ManifestDownloadTask::emitFailed); - connect(elementDownload, &Task::progress, this, &ManifestDownloadTask::setProgress); - connect(elementDownload, &Task::stepProgress, this, &ManifestDownloadTask::propagateStepProgress); - connect(elementDownload, &Task::status, this, &ManifestDownloadTask::setStatus); - connect(elementDownload, &Task::details, this, &ManifestDownloadTask::setDetails); - connect(this, &Task::aborted, elementDownload, &NetJob::abort); - connect(elementDownload, &NetJob::succeeded, [this] { emitSucceeded(); }); - elementDownload->start(); + connect(elementDownload.get(), &Task::failed, this, &ManifestDownloadTask::emitFailed); + connect(elementDownload.get(), &Task::progress, this, &ManifestDownloadTask::setProgress); + connect(elementDownload.get(), &Task::stepProgress, this, &ManifestDownloadTask::propagateStepProgress); + connect(elementDownload.get(), &Task::status, this, &ManifestDownloadTask::setStatus); + connect(elementDownload.get(), &Task::details, this, &ManifestDownloadTask::setDetails); + + connect(elementDownload.get(), &Task::succeeded, this, &ManifestDownloadTask::emitSucceeded); + m_task = elementDownload; + m_task->start(); } + +bool ManifestDownloadTask::abort() +{ + auto aborted = canAbort(); + if (m_task) + aborted = m_task->abort(); + emitAborted(); + return aborted; +}; } // namespace Java \ No newline at end of file diff --git a/launcher/java/download/ManifestDownloadTask.h b/launcher/java/download/ManifestDownloadTask.h index f0eaf95a6..ae9e0d0ed 100644 --- a/launcher/java/download/ManifestDownloadTask.h +++ b/launcher/java/download/ManifestDownloadTask.h @@ -31,6 +31,7 @@ class ManifestDownloadTask : public Task { [[nodiscard]] bool canAbort() const override { return true; } void executeTask() override; + virtual bool abort() override; private slots: void downloadJava(const QJsonDocument& doc); @@ -40,5 +41,6 @@ class ManifestDownloadTask : public Task { QString m_final_path; QString m_checksum_type; QString m_checksum_hash; + Task::Ptr m_task; }; } // namespace Java \ No newline at end of file From 2fb3e12492f7fd70f15fdaa6f8066e7420fdc01f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 16 Jun 2024 17:54:13 +0300 Subject: [PATCH 077/120] fix auto java install Signed-off-by: Trial97 --- launcher/minecraft/LaunchProfile.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/minecraft/LaunchProfile.cpp b/launcher/minecraft/LaunchProfile.cpp index 77072472c..468798850 100644 --- a/launcher/minecraft/LaunchProfile.cpp +++ b/launcher/minecraft/LaunchProfile.cpp @@ -166,7 +166,8 @@ void LaunchProfile::applyCompatibleJavaMajors(QList& javaMajor) } void LaunchProfile::applyCompatibleJavaName(QString javaName) { - m_compatibleJavaName = javaName; + if (!javaName.isEmpty()) + m_compatibleJavaName = javaName; } void LaunchProfile::applyLibrary(LibraryPtr library, const RuntimeContext& runtimeContext) From 1a66db78a989603a675e82d9cb30d91a319dff83 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Tue, 25 Jun 2024 15:17:51 +0300 Subject: [PATCH 078/120] Apply text change suggestions from code review Co-authored-by: seth Signed-off-by: Alexandru Ionut Tripon --- launcher/java/download/ArchiveDownloadTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/java/download/ArchiveDownloadTask.cpp b/launcher/java/download/ArchiveDownloadTask.cpp index 5aed70ede..71e78629b 100644 --- a/launcher/java/download/ArchiveDownloadTask.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -67,7 +67,7 @@ void ArchiveDownloadTask::extractJava(QString input) { setStatus(tr("Extracting java")); if (input.endsWith("tar")) { - setStatus(tr("Extracting java(the progress will not be reported for tar)")); + setStatus(tr("Extracting Java (Progress is not reported for tar archives)")); QFile in(input); if (!in.open(QFile::ReadOnly)) { emitFailed(tr("Unable to open supplied tar file.")); @@ -80,7 +80,7 @@ void ArchiveDownloadTask::extractJava(QString input) emitSucceeded(); return; } else if (input.endsWith("tar.gz") || input.endsWith("taz") || input.endsWith("tgz")) { - setStatus(tr("Extracting java(the progress will not be reported for tar)")); + setStatus(tr("Extracting Java (Progress is not reported for tar archives)")); if (!GZTar::extract(input, QDir(m_final_path).absolutePath())) { emitFailed(tr("Unable to extract supplied tar file.")); return; @@ -95,7 +95,7 @@ void ArchiveDownloadTask::extractJava(QString input) } auto files = zip->getFileNameList(); if (files.isEmpty()) { - emitFailed("Empty archive"); + emitFailed(tr("Empty archive")); return; } m_task = makeShared(zip, m_final_path, files[0]); From 52839774e64e488139ff7d3c8d9cf41ada43f947 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Tue, 25 Jun 2024 15:19:23 +0300 Subject: [PATCH 079/120] Apply suggestions from code review Co-authored-by: seth Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/widgets/JavaSettingsWidget.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index e16f650fc..dbd81cdd2 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -180,7 +180,7 @@ void JavaSettingsWidget::initialize() if (BuildConfig.JAVA_DOWNLOADER_ENABLED) { auto button = - CustomMessageBox::selectable(this, tr("Auto Java Download"), + CustomMessageBox::selectable(this, tr("Automatic Java Download"), tr("%1 can automatically download the correct Java version for each version of Minecraft..\n" "Do you want to enable Java auto-download?\n") .arg(BuildConfig.LAUNCHER_DISPLAYNAME), @@ -220,8 +220,8 @@ JavaSettingsWidget::ValidationStatus JavaSettingsWidget::validate() int button = QMessageBox::No; if (m_result.mojangPlatform == "32" && maxHeapSize() > 2048) { button = CustomMessageBox::selectable( - this, tr("Java x32 detected"), - tr("You selected an 32-bit java, but allocated more than 2048MiB as maximum memory.\n" + this, tr("32-bit Java detected"), + tr("You selected a 32-bit installation of Java, but allocated more than 2048MiB as maximum memory.\n" "%1 will not be able to start Minecraft.\n" "Do you wish to proceed?" "\n\n" @@ -232,9 +232,9 @@ JavaSettingsWidget::ValidationStatus JavaSettingsWidget::validate() } else { button = CustomMessageBox::selectable(this, tr("No Java version selected"), - tr("You didn't select a Java version or selected something that doesn't work.\n" + tr("You either didn't select a Java version or selected one that does not work.\n" "%1 will not be able to start Minecraft.\n" - "Do you wish to proceed without any Java?" + "Do you wish to proceed without a functional version of Java?" "\n\n" "You can change the Java version in the settings later.\n") .arg(BuildConfig.LAUNCHER_DISPLAYNAME), @@ -246,7 +246,7 @@ JavaSettingsWidget::ValidationStatus JavaSettingsWidget::validate() case QMessageBox::Yes: return ValidationStatus::JavaBad; case QMessageBox::Help: - DesktopServices::openUrl(QUrl(BuildConfig.HELP_URL.arg("java-wizzard"))); + DesktopServices::openUrl(QUrl(BuildConfig.HELP_URL.arg("java-wizard"))); /* fallthrough */ case QMessageBox::No: /* fallthrough */ @@ -515,7 +515,7 @@ void JavaSettingsWidget::updateThresholds() m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value")); } else if (observedMaxMemory > 2048 && m_result.is_64bit) { iconName = "status-bad"; - m_labelMaxMemIcon->setToolTip(tr("Because you're using 32 bit Java, you're exceeding the maximum possible allocation.")); + m_labelMaxMemIcon->setToolTip(tr("You are exceeding the maximum allocation supported by 32-bit installations of Java.")); } else { iconName = "status-good"; m_labelMaxMemIcon->setToolTip(""); From 4e9e7212a614fe2169ba0a760b765ab944382e53 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Tue, 25 Jun 2024 15:22:30 +0300 Subject: [PATCH 080/120] Apply suggestions from code review Co-authored-by: seth Signed-off-by: Alexandru Ionut Tripon --- launcher/minecraft/launch/AutoInstallJava.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index 95bfa1dec..98e381f3b 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -74,13 +74,13 @@ void AutoInstallJava::executeTask() auto java = std::dynamic_pointer_cast(javas->at(i)); if (java && packProfile->getProfile()->getCompatibleJavaMajors().contains(java->id.major())) { if (!java->is_64bit) { - emit logLine(tr("The automatic Java mechanism detected an x32 java."), MessageLevel::Info); + emit logLine(tr("The automatic Java mechanism detected a 32-bit installation of Java."), MessageLevel::Info); } setJavaPath(java->path); return; } } - emit logLine(tr("No compatible java version was found. Using the default one."), MessageLevel::Warning); + 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); @@ -91,7 +91,7 @@ void AutoInstallJava::executeTask() return; } if (m_supported_arch.isEmpty()) { - emit logLine(tr("Your system(%1 %2) is not compatible with auto java download. Using the default java path.") + 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(); @@ -99,8 +99,8 @@ void AutoInstallJava::executeTask() } auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName(); if (wantedJavaName.isEmpty()) { - emit logLine(tr("Your meta informtation is old or doesn't have the information necesary to determine what java should be used. " - "Using the default java path."), + 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; @@ -127,7 +127,7 @@ void AutoInstallJava::setJavaPath(QString path) auto settings = m_instance->settings(); settings->set("OverrideJavaLocation", true); settings->set("JavaPath", path); - emit logLine(tr("Compatible java found at: %1.").arg(path), MessageLevel::Info); + emit logLine(tr("Compatible Java found at: %1.").arg(path), MessageLevel::Info); emitSucceeded(); } @@ -148,7 +148,7 @@ void AutoInstallJava::setJavaPathFromPartial() if (QFileInfo::exists(finalPath)) { setJavaPath(finalPath); } else { - emit logLine(tr("No compatible java version was found(the binary file doesn't exists). Using the default one."), + emit logLine(tr("No compatible Java version was found (the binary file does not exist). Using the default one."), MessageLevel::Warning); emitSucceeded(); } @@ -201,9 +201,9 @@ void AutoInstallJava::tryNextMajorJava() auto wantedJavaName = packProfile->getProfile()->getCompatibleJavaName(); auto majorJavaVersions = packProfile->getProfile()->getCompatibleJavaMajors(); if (m_majorJavaVersionIndex >= majorJavaVersions.length()) { - emit logLine(tr("No Java versions found for your operating system: %1 %2").arg(SysInfo::currentSystem(), SysInfo::useQTForArch()), + 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 java version was found. Using the default one."), MessageLevel::Warning); + emit logLine(tr("No compatible version of Java was found. Using the default one."), MessageLevel::Warning); emitSucceeded(); return; } From 555c4a7c59f4f09810615ecd5152b48a6fa73d51 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Tue, 25 Jun 2024 15:33:11 +0300 Subject: [PATCH 081/120] Apply suggestions from code review Co-authored-by: seth Signed-off-by: Alexandru Ionut Tripon --- launcher/java/download/ManifestDownloadTask.cpp | 2 +- launcher/minecraft/launch/VerifyJavaInstall.cpp | 2 +- launcher/ui/pages/global/JavaPage.cpp | 4 ++-- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/launcher/java/download/ManifestDownloadTask.cpp b/launcher/java/download/ManifestDownloadTask.cpp index 1fcc6f172..836afeaac 100644 --- a/launcher/java/download/ManifestDownloadTask.cpp +++ b/launcher/java/download/ManifestDownloadTask.cpp @@ -61,7 +61,7 @@ void ManifestDownloadTask::executeTask() QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*files, &parse_error); if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response at " << parse_error.offset << " reason: " << parse_error.errorString(); + qWarning() << "Error while parsing JSON response at " << parse_error.offset << ". Reason: " << parse_error.errorString(); qWarning() << *files; emitFailed(parse_error.errorString()); return; diff --git a/launcher/minecraft/launch/VerifyJavaInstall.cpp b/launcher/minecraft/launch/VerifyJavaInstall.cpp index 5f8b35b02..1e7448089 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.cpp +++ b/launcher/minecraft/launch/VerifyJavaInstall.cpp @@ -56,7 +56,7 @@ void VerifyJavaInstall::executeTask() if (javaArchitecture == "32" && maxMemAlloc > 2048) { emit logLine(tr("Max memory allocation exceeds the supported value.\n" - "The selected java is 32-bit and doesn't support more than 2048MiB of RAM.\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); } diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index c8bbf6361..ad37fa740 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -161,8 +161,8 @@ void JavaPage::on_javaDetectBtn_clicked() ui->javaPathTextBox->setText(java->path); if (!java->is_64bit && APPLICATION->settings()->get("MaxMemAlloc").toInt() > 2048) { CustomMessageBox::selectable(this, tr("Confirm Selection"), - tr("You selected a 32 bit java version.\n" - "This means that will not support more than 2048MiB of RAM.\n" + tr("You selected a 32-bit version of Java.\n" + "This installation does not support more than 2048MiB of RAM.\n" "Please make sure that the maximum memory value is lower."), QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok) ->exec(); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index fa52f2c51..6e6b1db57 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -418,8 +418,8 @@ void InstanceSettingsPage::on_javaDetectBtn_clicked() if (!java->is_64bit && m_settings->get("MaxMemAlloc").toInt() > 2048) { CustomMessageBox::selectable(this, tr("Confirm Selection"), - tr("You selected a 32 bit java version.\n" - "This means that will not support more than 2048MiB of RAM.\n" + tr("You selected a 32-bit version of Java.\n" + "This installation does not support more than 2048MiB of RAM.\n" "Please make sure that the maximum memory value is lower."), QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Ok) ->exec(); From 7c38edc93dda3fe4f177cb182314870e314367d8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 25 Jun 2024 16:10:05 +0300 Subject: [PATCH 082/120] Apply suggestion from code review Signed-off-by: Trial97 --- launcher/java/JavaMetadata.cpp | 10 ++- launcher/java/JavaMetadata.h | 2 +- launcher/java/JavaUtils.cpp | 21 +++--- launcher/java/JavaUtils.h | 1 + .../java/download/ArchiveDownloadTask.cpp | 71 ++++++++++--------- launcher/minecraft/launch/AutoInstallJava.cpp | 20 +++--- launcher/ui/java/InstallJavaDialog.cpp | 6 +- launcher/ui/widgets/JavaSettingsWidget.cpp | 11 +-- 8 files changed, 75 insertions(+), 67 deletions(-) diff --git a/launcher/java/JavaMetadata.cpp b/launcher/java/JavaMetadata.cpp index 2272470a8..2d68f55c8 100644 --- a/launcher/java/JavaMetadata.cpp +++ b/launcher/java/JavaMetadata.cpp @@ -31,8 +31,10 @@ DownloadType parseDownloadType(QString javaDownload) { if (javaDownload == "manifest") return DownloadType::Manifest; - // if (javaDownload == "archive") - return DownloadType::Archive; + else if (javaDownload == "archive") + return DownloadType::Archive; + else + return DownloadType::Unknown; } QString downloadTypeToString(DownloadType javaDownload) { @@ -41,8 +43,10 @@ QString downloadTypeToString(DownloadType javaDownload) return "manifest"; case DownloadType::Archive: return "archive"; + case DownloadType::Unknown: + break; } - return ""; + return "unknown"; } MetadataPtr parseJavaMeta(const QJsonObject& in) { diff --git a/launcher/java/JavaMetadata.h b/launcher/java/JavaMetadata.h index 5281f2e27..77a42fd78 100644 --- a/launcher/java/JavaMetadata.h +++ b/launcher/java/JavaMetadata.h @@ -28,7 +28,7 @@ namespace Java { -enum class DownloadType { Manifest, Archive }; +enum class DownloadType { Manifest, Archive, Unknown }; class Metadata : public BaseVersion { public: diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 42d3ef6ab..c0f64ad37 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -463,12 +463,10 @@ QString JavaUtils::getJavaCheckPath() QStringList getMinecraftJavaBundle() { - QString executable = "java"; QStringList processpaths; #if defined(Q_OS_OSX) processpaths << FS::PathCombine(QDir::homePath(), FS::PathCombine("Library", "Application Support", "minecraft", "runtime")); #elif defined(Q_OS_WIN32) - executable += "w.exe"; auto appDataPath = QProcessEnvironment::systemEnvironment().value("APPDATA", ""); processpaths << FS::PathCombine(QFileInfo(appDataPath).absoluteFilePath(), ".minecraft", "runtime"); @@ -493,7 +491,7 @@ QStringList getMinecraftJavaBundle() auto binFound = false; for (auto& entry : entries) { if (entry.baseName() == "bin") { - javas.append(FS::PathCombine(entry.canonicalFilePath(), executable)); + javas.append(FS::PathCombine(entry.canonicalFilePath(), JavaUtils::javaExecutable)); binFound = true; break; } @@ -507,19 +505,20 @@ QStringList getMinecraftJavaBundle() return javas; } +#if defined(Q_OS_WIN32) +const QString JavaUtils::javaExecutable = "javaw.exe"; +#else +const QString JavaUtils::javaExecutable = "java"; +#endif + QStringList getPrismJavaBundle() { QList javas; - QString executable = "java"; -#if defined(Q_OS_WIN32) - executable += "w.exe"; -#endif - auto scanDir = [&](QString prefix) { - javas.append(FS::PathCombine(prefix, "jre", "bin", executable)); - javas.append(FS::PathCombine(prefix, "bin", executable)); - javas.append(FS::PathCombine(prefix, executable)); + javas.append(FS::PathCombine(prefix, "jre", "bin", JavaUtils::javaExecutable)); + javas.append(FS::PathCombine(prefix, "bin", JavaUtils::javaExecutable)); + javas.append(FS::PathCombine(prefix, JavaUtils::javaExecutable)); }; auto scanJavaDir = [&](const QString& dirPath) { QDir dir(dirPath); diff --git a/launcher/java/JavaUtils.h b/launcher/java/JavaUtils.h index aa5315a19..eb3a17316 100644 --- a/launcher/java/JavaUtils.h +++ b/launcher/java/JavaUtils.h @@ -42,4 +42,5 @@ class JavaUtils : public QObject { #endif static QString getJavaCheckPath(); + static const QString javaExecutable; }; diff --git a/launcher/java/download/ArchiveDownloadTask.cpp b/launcher/java/download/ArchiveDownloadTask.cpp index 71e78629b..af5381dfc 100644 --- a/launcher/java/download/ArchiveDownloadTask.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -87,43 +87,46 @@ void ArchiveDownloadTask::extractJava(QString input) } emitSucceeded(); return; - } - auto zip = std::make_shared(input); - if (!zip->open(QuaZip::mdUnzip)) { - emitFailed(tr("Unable to open supplied zip file.")); - return; - } - auto files = zip->getFileNameList(); - if (files.isEmpty()) { - emitFailed(tr("Empty archive")); - return; - } - m_task = makeShared(zip, m_final_path, files[0]); + } else if (input.endsWith("zip")) { + auto zip = std::make_shared(input); + if (!zip->open(QuaZip::mdUnzip)) { + emitFailed(tr("Unable to open supplied zip file.")); + return; + } + auto files = zip->getFileNameList(); + if (files.isEmpty()) { + emitFailed(tr("No files were found in the supplied zip file,")); + return; + } + m_task = makeShared(zip, m_final_path, files[0]); - auto progressStep = std::make_shared(); - connect(m_task.get(), &Task::finished, this, [this, progressStep] { - progressStep->state = TaskStepState::Succeeded; - stepProgress(*progressStep); - }); + auto progressStep = std::make_shared(); + connect(m_task.get(), &Task::finished, this, [this, progressStep] { + progressStep->state = TaskStepState::Succeeded; + stepProgress(*progressStep); + }); - connect(m_task.get(), &Task::succeeded, this, &ArchiveDownloadTask::emitSucceeded); - connect(m_task.get(), &Task::aborted, this, &ArchiveDownloadTask::emitAborted); - connect(m_task.get(), &Task::failed, this, [this, progressStep](QString reason) { - progressStep->state = TaskStepState::Failed; - stepProgress(*progressStep); - emitFailed(reason); - }); - connect(m_task.get(), &Task::stepProgress, this, &ArchiveDownloadTask::propagateStepProgress); + connect(m_task.get(), &Task::succeeded, this, &ArchiveDownloadTask::emitSucceeded); + connect(m_task.get(), &Task::aborted, this, &ArchiveDownloadTask::emitAborted); + connect(m_task.get(), &Task::failed, this, [this, progressStep](QString reason) { + progressStep->state = TaskStepState::Failed; + stepProgress(*progressStep); + emitFailed(reason); + }); + connect(m_task.get(), &Task::stepProgress, this, &ArchiveDownloadTask::propagateStepProgress); - connect(m_task.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { - progressStep->update(current, total); - stepProgress(*progressStep); - }); - connect(m_task.get(), &Task::status, this, [this, progressStep](QString status) { - progressStep->status = status; - stepProgress(*progressStep); - }); - m_task->start(); + connect(m_task.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { + progressStep->update(current, total); + stepProgress(*progressStep); + }); + connect(m_task.get(), &Task::status, this, [this, progressStep](QString status) { + progressStep->status = status; + stepProgress(*progressStep); + }); + m_task->start(); + } + + emitFailed(tr("Could not determine archive type!")); } bool ArchiveDownloadTask::abort() diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index 98e381f3b..c77b9b105 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -44,6 +44,7 @@ #include "SysInfo.h" #include "java/JavaInstall.h" #include "java/JavaInstallList.h" +#include "java/JavaUtils.h" #include "java/JavaVersion.h" #include "java/download/ArchiveDownloadTask.h" #include "java/download/ManifestDownloadTask.h" @@ -91,7 +92,7 @@ void AutoInstallJava::executeTask() 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.") + 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(); @@ -99,7 +100,8 @@ void AutoInstallJava::executeTask() } 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. " + 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(); @@ -133,17 +135,13 @@ void AutoInstallJava::setJavaPath(QString path) void AutoInstallJava::setJavaPathFromPartial() { - QString executable = "java"; -#if defined(Q_OS_WIN32) - executable += "w.exe"; -#endif 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", executable); + auto relativeBinary = FS::PathCombine(javaName, "bin", JavaUtils::javaExecutable); auto finalPath = javaDir.absoluteFilePath(relativeBinary); if (QFileInfo::exists(finalPath)) { setJavaPath(finalPath); @@ -169,6 +167,9 @@ void AutoInstallJava::downloadJava(Meta::Version::Ptr version, QString javaName) case Java::DownloadType::Archive: m_current_task = makeShared(java->url, final_path, java->checksumType, java->checksumHash); break; + case Java::DownloadType::Unknown: + emitFailed(tr("Could not determine Java download type!")); + return; } auto deletePath = [final_path] { FS::deletePath(final_path); }; connect(m_current_task.get(), &Task::failed, this, [this, deletePath](QString reason) { @@ -201,8 +202,9 @@ void AutoInstallJava::tryNextMajorJava() 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 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; diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index d92402236..1a4b4cc58 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -211,6 +211,7 @@ void InstallDialog::done(int result) if (meta) { Task::Ptr task; auto final_path = FS::PathCombine(APPLICATION->javaPath(), meta->m_name); + auto deletePath = [final_path] { FS::deletePath(final_path); }; switch (meta->downloadType) { case Java::DownloadType::Manifest: task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); @@ -218,8 +219,11 @@ void InstallDialog::done(int result) case Java::DownloadType::Archive: task = makeShared(meta->url, final_path, meta->checksumType, meta->checksumHash); break; + case Java::DownloadType::Unknown: + QString error = QString(tr("Could not determine Java download type!")); + CustomMessageBox::selectable(this, tr("Error"), error, QMessageBox::Warning)->show(); + deletePath(); } - auto deletePath = [final_path] { FS::deletePath(final_path); }; connect(task.get(), &Task::failed, this, [this, &deletePath](QString reason) { QString error = QString("Java download failed: %1").arg(reason); CustomMessageBox::selectable(this, tr("Error"), error, QMessageBox::Warning)->show(); diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index dbd81cdd2..ec1ed0605 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -339,17 +339,12 @@ void JavaSettingsWidget::javaVersionSelected(BaseVersion::Ptr version) void JavaSettingsWidget::on_javaBrowseBtn_clicked() { - QString filter; -#if defined Q_OS_WIN32 - filter = "Java (javaw.exe)"; -#else - filter = "Java (java)"; -#endif - QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"), QString(), filter); + auto filter = QString("Java (%1)").arg(JavaUtils::javaExecutable); + auto raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"), QString(), filter); if (raw_path.isEmpty()) { return; } - QString cooked_path = FS::NormalizePath(raw_path); + auto cooked_path = FS::NormalizePath(raw_path); m_javaPathTextBox->setText(cooked_path); checkJavaPath(cooked_path); } From 4ad19cded588dba201f3d1cdc2db248694a6101d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 28 Jun 2024 20:45:54 +0300 Subject: [PATCH 083/120] format Signed-off-by: Trial97 --- launcher/minecraft/launch/AutoInstallJava.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index c77b9b105..eefed9cf5 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -56,7 +56,7 @@ AutoInstallJava::AutoInstallJava(LaunchTask* parent) : LaunchStep(parent) , m_instance(std::dynamic_pointer_cast(m_parent->instance())) - , m_supported_arch(SysInfo::getSupportedJavaArchitecture()){}; + , m_supported_arch(SysInfo::getSupportedJavaArchitecture()) {}; void AutoInstallJava::executeTask() { From 2af6902b4204b93b97c08162f7980e075d63e532 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 17 Jun 2024 01:33:11 +0300 Subject: [PATCH 084/120] validate metadata on launch Signed-off-by: Trial97 --- launcher/Application.cpp | 4 +- launcher/java/JavaInstallList.h | 2 +- launcher/meta/BaseEntity.cpp | 137 +++++++++++------- launcher/meta/BaseEntity.h | 47 ++++-- launcher/meta/Index.cpp | 29 +++- launcher/meta/Index.h | 7 +- launcher/meta/JsonFormat.cpp | 4 + launcher/meta/JsonFormat.h | 2 - launcher/meta/Version.cpp | 6 +- launcher/meta/Version.h | 2 +- launcher/meta/VersionList.cpp | 47 ++++-- launcher/meta/VersionList.h | 3 +- launcher/minecraft/AssetsUtils.cpp | 3 +- launcher/minecraft/Component.cpp | 24 ++- launcher/minecraft/Component.h | 1 - launcher/minecraft/ComponentUpdateTask.cpp | 41 +----- launcher/minecraft/ComponentUpdateTask.h | 1 + launcher/minecraft/Library.cpp | 3 +- launcher/minecraft/update/AssetUpdateTask.cpp | 3 +- .../atlauncher/ATLPackInstallTask.cpp | 54 ++----- .../modplatform/flame/FlamePackExportTask.cpp | 2 +- .../modrinth/ModrinthPackExportTask.cpp | 6 +- .../technic/SolderPackInstallTask.cpp | 3 +- launcher/net/ChecksumValidator.h | 3 + launcher/translations/TranslationsModel.cpp | 3 +- launcher/ui/pages/instance/VersionPage.h | 1 + .../ui/pages/modplatform/TexturePackModel.cpp | 9 +- .../ui/pages/modplatform/TexturePackModel.h | 1 + launcher/ui/widgets/VersionSelectWidget.cpp | 18 +-- launcher/ui/widgets/VersionSelectWidget.h | 2 +- 30 files changed, 253 insertions(+), 215 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 6d30d1101..f8111b938 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -47,7 +47,6 @@ #include "net/PasteUpload.h" #include "pathmatcher/MultiMatcher.h" #include "pathmatcher/SimplePrefixMatcher.h" -#include "settings/INIFile.h" #include "tools/GenericProfiler.h" #include "ui/InstanceWindow.h" #include "ui/MainWindow.h" @@ -106,7 +105,7 @@ #include "icons/IconList.h" #include "net/HttpMetaCache.h" -#include "java/JavaUtils.h" +#include "java/JavaInstallList.h" #include "updater/ExternalUpdater.h" @@ -151,6 +150,7 @@ #endif #if defined Q_OS_WIN32 +#include #include "WindowsConsole.h" #endif diff --git a/launcher/java/JavaInstallList.h b/launcher/java/JavaInstallList.h index 1eebadf23..f629af174 100644 --- a/launcher/java/JavaInstallList.h +++ b/launcher/java/JavaInstallList.h @@ -35,7 +35,7 @@ class JavaInstallList : public BaseVersionList { public: explicit JavaInstallList(QObject* parent = 0); - Task::Ptr getLoadTask() override; + [[nodiscard]] Task::Ptr getLoadTask() override; bool isLoaded() override; const BaseVersion::Ptr at(int i) const override; int count() const override; diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index e74406752..581eaa7f4 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -17,17 +17,23 @@ #include "FileSystem.h" #include "Json.h" +#include "modplatform/helpers/HashUtils.h" #include "net/ApiDownload.h" +#include "net/ChecksumValidator.h" #include "net/HttpMetaCache.h" +#include "net/Mode.h" #include "net/NetJob.h" #include "Application.h" #include "BuildConfig.h" +#include "tasks/Task.h" + +namespace Meta { class ParsingValidator : public Net::Validator { public: /* con/des */ - ParsingValidator(Meta::BaseEntity* entity) : m_entity(entity) {}; - virtual ~ParsingValidator() {}; + ParsingValidator(BaseEntity* entity) : m_entity(entity){}; + virtual ~ParsingValidator() = default; public: /* methods */ bool init(QNetworkRequest&) override { return true; } @@ -53,92 +59,113 @@ class ParsingValidator : public Net::Validator { private: /* data */ QByteArray m_data; - Meta::BaseEntity* m_entity; + BaseEntity* m_entity; }; -Meta::BaseEntity::~BaseEntity() {} - -QUrl Meta::BaseEntity::url() const +QUrl BaseEntity::url() const { auto s = APPLICATION->settings(); QString metaOverride = s->get("MetaURLOverride").toString(); if (metaOverride.isEmpty()) { return QUrl(BuildConfig.META_URL).resolved(localFilename()); - } else { - return QUrl(metaOverride).resolved(localFilename()); } + return QUrl(metaOverride).resolved(localFilename()); } -bool Meta::BaseEntity::loadLocalFile() +Task::Ptr BaseEntity::loadTask(Net::Mode mode) { - const QString fname = QDir("meta").absoluteFilePath(localFilename()); - if (!QFile::exists(fname)) { - return false; - } - // TODO: check if the file has the expected checksum - try { - auto doc = Json::requireDocument(fname, fname); - auto obj = Json::requireObject(doc, fname); - parse(obj); - return true; - } catch (const Exception& e) { - qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause()); - // just make sure it's gone and we never consider it again. - return !FS::deletePath(fname); + if (m_task && m_task->isRunning()) { + return m_task; } + m_task.reset(new BaseEntityLoadTask(this, mode)); + return m_task; } -void Meta::BaseEntity::load(Net::Mode loadType) +bool BaseEntity::isLoaded() const { + return m_load_status != LoadStatus::NotLoaded; +} + +void BaseEntity::setSha256(QString sha256) +{ + m_sha256 = sha256; +} + +BaseEntity::LoadStatus BaseEntity::status() const +{ + return m_load_status; +} + +BaseEntityLoadTask::BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode) : m_entity(parent), m_mode(mode) {} + +void BaseEntityLoadTask::executeTask() +{ + const QString fname = QDir("meta").absoluteFilePath(m_entity->localFilename()); // load local file if nothing is loaded yet - if (!isLoaded()) { - if (loadLocalFile()) { - m_loadStatus = LoadStatus::Local; + if (m_entity->m_load_status != BaseEntity::LoadStatus::NotLoaded && QFile::exists(fname)) { + setStatus(tr("Loading local file")); + try { + auto fileData = FS::read(fname); + m_entity->m_file_sha256 = Hashing::hash(fileData, Hashing::Algorithm::Sha256); + if (m_mode == Net::Mode::Online && !m_entity->m_sha256.isEmpty() && m_entity->m_sha256 != m_entity->m_file_sha256) { + FS::deletePath(fname); + } else { + auto doc = Json::requireDocument(fileData, fname); + auto obj = Json::requireObject(doc, fname); + m_entity->parse(obj); + m_entity->m_load_status = BaseEntity::LoadStatus::Local; + } + } catch (const Exception& e) { + qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause()); + // just make sure it's gone and we never consider it again. + FS::deletePath(fname); } } // if we need remote update, run the update task - if (loadType == Net::Mode::Offline || !shouldStartRemoteUpdate()) { + if (m_mode == Net::Mode::Offline || (!m_entity->m_sha256.isEmpty() && m_entity->m_sha256 == m_entity->m_file_sha256)) { + emitSucceeded(); return; } - m_updateTask.reset(new NetJob(QObject::tr("Download of meta file %1").arg(localFilename()), APPLICATION->network())); - auto url = this->url(); - auto entry = APPLICATION->metacache()->resolveEntry("meta", localFilename()); + m_task.reset(new NetJob(QObject::tr("Download of meta file %1").arg(m_entity->localFilename()), APPLICATION->network())); + auto url = m_entity->url(); + auto entry = APPLICATION->metacache()->resolveEntry("meta", m_entity->localFilename()); entry->setStale(true); auto dl = Net::ApiDownload::makeCached(url, entry); /* * The validator parses the file and loads it into the object. * If that fails, the file is not written to storage. */ - dl->addValidator(new ParsingValidator(this)); - m_updateTask->addNetAction(dl); - m_updateStatus = UpdateStatus::InProgress; - QObject::connect(m_updateTask.get(), &NetJob::succeeded, [&]() { - m_loadStatus = LoadStatus::Remote; - m_updateStatus = UpdateStatus::Succeeded; - m_updateTask.reset(); + if (!m_entity->m_sha256.isEmpty()) + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Algorithm::Sha256, m_entity->m_sha256)); + dl->addValidator(new ParsingValidator(m_entity)); + m_task->addNetAction(dl); + connect(m_task.get(), &Task::failed, this, &BaseEntityLoadTask::emitFailed); + connect(m_task.get(), &Task::succeeded, this, &BaseEntityLoadTask::emitSucceeded); + connect(m_task.get(), &Task::succeeded, this, [this]() { + m_entity->m_load_status = BaseEntity::LoadStatus::Remote; + m_entity->m_file_sha256 = m_entity->m_sha256; }); - QObject::connect(m_updateTask.get(), &NetJob::failed, [&]() { - m_updateStatus = UpdateStatus::Failed; - m_updateTask.reset(); - }); - m_updateTask->start(); + + connect(m_task.get(), &Task::progress, this, &Task::setProgress); + connect(m_task.get(), &Task::stepProgress, this, &BaseEntityLoadTask::propagateStepProgress); + connect(m_task.get(), &Task::status, this, &Task::setStatus); + connect(m_task.get(), &Task::details, this, &Task::setDetails); + + m_task->start(); } -bool Meta::BaseEntity::isLoaded() const +bool BaseEntityLoadTask::canAbort() const { - return m_loadStatus > LoadStatus::NotLoaded; + return m_task ? m_task->canAbort() : false; } -bool Meta::BaseEntity::shouldStartRemoteUpdate() const +bool BaseEntityLoadTask::abort() { - // TODO: version-locks and offline mode? - return m_updateStatus != UpdateStatus::InProgress; -} - -Task::Ptr Meta::BaseEntity::getCurrentTask() -{ - if (m_updateStatus == UpdateStatus::InProgress) { - return m_updateTask; + if (m_task) { + Task::abort(); + return m_task->abort(); } - return nullptr; + return Task::abort(); } + +} // namespace Meta diff --git a/launcher/meta/BaseEntity.h b/launcher/meta/BaseEntity.h index 1336a5217..17aa0cb87 100644 --- a/launcher/meta/BaseEntity.h +++ b/launcher/meta/BaseEntity.h @@ -17,38 +17,57 @@ #include #include -#include "QObjectPtr.h" #include "net/Mode.h" #include "net/NetJob.h" +#include "tasks/Task.h" namespace Meta { +class BaseEntityLoadTask; class BaseEntity { + friend BaseEntityLoadTask; + public: /* types */ using Ptr = std::shared_ptr; enum class LoadStatus { NotLoaded, Local, Remote }; - enum class UpdateStatus { NotDone, InProgress, Failed, Succeeded }; public: - virtual ~BaseEntity(); - - virtual void parse(const QJsonObject& obj) = 0; + virtual ~BaseEntity() = default; virtual QString localFilename() const = 0; virtual QUrl url() const; - bool isLoaded() const; - bool shouldStartRemoteUpdate() const; + LoadStatus status() const; - void load(Net::Mode loadType); - Task::Ptr getCurrentTask(); + /* for parsers */ + void setSha256(QString sha256); - protected: /* methods */ - bool loadLocalFile(); + virtual void parse(const QJsonObject& obj) = 0; + [[nodiscard]] Task::Ptr loadTask(Net::Mode loadType = Net::Mode::Online); + + protected: + QString m_sha256; // the expected sha256 + QString m_file_sha256; // the file sha256 private: - LoadStatus m_loadStatus = LoadStatus::NotLoaded; - UpdateStatus m_updateStatus = UpdateStatus::NotDone; - NetJob::Ptr m_updateTask; + LoadStatus m_load_status = LoadStatus::NotLoaded; + Task::Ptr m_task; +}; + +class BaseEntityLoadTask : public Task { + Q_OBJECT + + public: + explicit BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode); + ~BaseEntityLoadTask() override = default; + + virtual void executeTask() override; + virtual bool canAbort() const override; + virtual bool abort() override; + + private: + BaseEntity* m_entity; + Net::Mode m_mode; + NetJob::Ptr m_task; }; } // namespace Meta diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index 657019f8a..ddcebc453 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -16,7 +16,10 @@ #include "Index.h" #include "JsonFormat.h" +#include "QObjectPtr.h" #include "VersionList.h" +#include "meta/BaseEntity.h" +#include "tasks/SequentialTask.h" namespace Meta { Index::Index(QObject* parent) : QAbstractListModel(parent) {} @@ -51,14 +54,17 @@ QVariant Index::data(const QModelIndex& index, int role) const } return QVariant(); } + int Index::rowCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : m_lists.size(); } + int Index::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : 1; } + QVariant Index::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0) { @@ -79,6 +85,7 @@ VersionList::Ptr Index::get(const QString& uid) if (!out) { out = std::make_shared(uid); m_uids[uid] = out; + m_lists.append(out); } return out; } @@ -96,7 +103,7 @@ void Index::parse(const QJsonObject& obj) void Index::merge(const std::shared_ptr& other) { - const QVector lists = std::dynamic_pointer_cast(other)->m_lists; + const QVector lists = other->m_lists; // initial load, no need to merge if (m_lists.isEmpty()) { beginResetModel(); @@ -123,7 +130,23 @@ void Index::merge(const std::shared_ptr& other) void Index::connectVersionList(const int row, const VersionList::Ptr& list) { - connect(list.get(), &VersionList::nameChanged, this, - [this, row]() { emit dataChanged(index(row), index(row), QVector() << Qt::DisplayRole); }); + connect(list.get(), &VersionList::nameChanged, this, [this, row] { emit dataChanged(index(row), index(row), { Qt::DisplayRole }); }); +} + +Task::Ptr Index::loadVersion(const QString& uid, const QString& version, Net::Mode mode, bool force) +{ + if (mode == Net::Mode::Offline) { + return get(uid, version)->loadTask(mode); + } + + auto versionList = get(uid); + auto loadTask = makeShared( + this, tr("Load meta for %1:%2", "This is for the task name that loads the meta index.").arg(uid, version)); + if (status() != BaseEntity::LoadStatus::Remote || force) { + loadTask->addTask(this->loadTask(mode)); + } + loadTask->addTask(versionList->loadTask(mode)); + loadTask->addTask(versionList->getVersion(version)->loadTask(mode)); + return loadTask; } } // namespace Meta diff --git a/launcher/meta/Index.h b/launcher/meta/Index.h index 2c650ce2f..e54cdd88b 100644 --- a/launcher/meta/Index.h +++ b/launcher/meta/Index.h @@ -16,10 +16,10 @@ #pragma once #include -#include #include "BaseEntity.h" #include "meta/VersionList.h" +#include "net/Mode.h" class Task; @@ -30,6 +30,7 @@ class Index : public QAbstractListModel, public BaseEntity { public: explicit Index(QObject* parent = nullptr); explicit Index(const QVector& lists, QObject* parent = nullptr); + virtual ~Index() = default; enum { UidRole = Qt::UserRole, NameRole, ListPtrRole }; @@ -47,8 +48,12 @@ class Index : public QAbstractListModel, public BaseEntity { QVector lists() const { return m_lists; } + Task::Ptr loadVersion(const QString& uid, const QString& version = {}, Net::Mode mode = Net::Mode::Online, bool force = false); + public: // for usage by parsers only void merge(const std::shared_ptr& other); + + protected: void parse(const QJsonObject& obj) override; private: diff --git a/launcher/meta/JsonFormat.cpp b/launcher/meta/JsonFormat.cpp index 6c993f720..86af7277e 100644 --- a/launcher/meta/JsonFormat.cpp +++ b/launcher/meta/JsonFormat.cpp @@ -41,6 +41,7 @@ static std::shared_ptr parseIndexInternal(const QJsonObject& obj) std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject& obj) { VersionList::Ptr list = std::make_shared(requireString(obj, "uid")); list->setName(ensureString(obj, "name", QString())); + list->setSha256(ensureString(obj, "sha256", QString())); return list; }); return std::make_shared(lists); @@ -58,6 +59,9 @@ static Version::Ptr parseCommonVersion(const QString& uid, const QJsonObject& ob parseRequires(obj, &reqs, "requires"); parseRequires(obj, &conflicts, "conflicts"); version->setRequires(reqs, conflicts); + if (auto sha256 = ensureString(obj, "sha256", QString()); !sha256.isEmpty()) { + version->setSha256(sha256); + } return version; } diff --git a/launcher/meta/JsonFormat.h b/launcher/meta/JsonFormat.h index d474bcc39..7fbf808a7 100644 --- a/launcher/meta/JsonFormat.h +++ b/launcher/meta/JsonFormat.h @@ -16,11 +16,9 @@ #pragma once #include -#include #include #include "Exception.h" -#include "meta/BaseEntity.h" namespace Meta { class Index; diff --git a/launcher/meta/Version.cpp b/launcher/meta/Version.cpp index 655a20b93..74e71e91c 100644 --- a/launcher/meta/Version.cpp +++ b/launcher/meta/Version.cpp @@ -18,12 +18,9 @@ #include #include "JsonFormat.h" -#include "minecraft/PackProfile.h" Meta::Version::Version(const QString& uid, const QString& version) : BaseVersion(), m_uid(uid), m_version(version) {} -Meta::Version::~Version() {} - QString Meta::Version::descriptor() { return m_version; @@ -71,6 +68,9 @@ void Meta::Version::mergeFromList(const Meta::Version::Ptr& other) if (m_volatile != other->m_volatile) { setVolatile(other->m_volatile); } + if (!other->m_sha256.isEmpty()) { + m_sha256 = other->m_sha256; + } } void Meta::Version::merge(const Version::Ptr& other) diff --git a/launcher/meta/Version.h b/launcher/meta/Version.h index 24da12d6d..149af86f6 100644 --- a/launcher/meta/Version.h +++ b/launcher/meta/Version.h @@ -38,7 +38,7 @@ class Version : public QObject, public BaseVersion, public BaseEntity { using Ptr = std::shared_ptr; explicit Version(const QString& uid, const QString& version); - virtual ~Version(); + virtual ~Version() = default; QString descriptor() override; QString name() override; diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index 7b7ae1fa3..f7269c57f 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -17,8 +17,13 @@ #include +#include "Application.h" +#include "Index.h" #include "JsonFormat.h" #include "Version.h" +#include "meta/BaseEntity.h" +#include "net/Mode.h" +#include "tasks/SequentialTask.h" namespace Meta { VersionList::VersionList(const QString& uid, QObject* parent) : BaseVersionList(parent), m_uid(uid) @@ -28,8 +33,11 @@ VersionList::VersionList(const QString& uid, QObject* parent) : BaseVersionList( Task::Ptr VersionList::getLoadTask() { - load(Net::Mode::Online); - return getCurrentTask(); + auto loadTask = + makeShared(this, tr("Load meta for %1", "This is for the task name that loads the meta index.").arg(m_uid)); + loadTask->addTask(APPLICATION->metadataIndex()->loadTask(Net::Mode::Online)); + loadTask->addTask(this->loadTask(Net::Mode::Online)); + return loadTask; } bool VersionList::isLoaded() @@ -191,6 +199,9 @@ void VersionList::mergeFromIndex(const VersionList::Ptr& other) if (m_name != other->m_name) { setName(other->m_name); } + if (!other->m_sha256.isEmpty()) { + m_sha256 = other->m_sha256; + } } void VersionList::merge(const VersionList::Ptr& other) @@ -198,23 +209,27 @@ void VersionList::merge(const VersionList::Ptr& other) if (m_name != other->m_name) { setName(other->m_name); } + if (!other->m_sha256.isEmpty()) { + m_sha256 = other->m_sha256; + } // TODO: do not reset the whole model. maybe? beginResetModel(); - m_versions.clear(); if (other->m_versions.isEmpty()) { qWarning() << "Empty list loaded ..."; } - for (const Version::Ptr& version : other->m_versions) { + for (auto version : other->m_versions) { // we already have the version. merge the contents if (m_lookup.contains(version->version())) { - m_lookup.value(version->version())->mergeFromList(version); + auto existing = m_lookup.value(version->version()); + existing->mergeFromList(version); + version = existing; } else { - m_lookup.insert(version->uid(), version); + m_lookup.insert(version->version(), version); + // connect it. + setupAddedVersion(m_versions.size(), version); + m_versions.append(version); } - // connect it. - setupAddedVersion(m_versions.size(), version); - m_versions.append(version); m_recommended = getBetterVersion(m_recommended, version); } endResetModel(); @@ -222,14 +237,16 @@ void VersionList::merge(const VersionList::Ptr& other) void VersionList::setupAddedVersion(const int row, const Version::Ptr& version) { - // FIXME: do not disconnect from everythin, disconnect only the lambdas here - version->disconnect(); + disconnect(version.get(), &Version::requiresChanged, this, nullptr); + disconnect(version.get(), &Version::timeChanged, this, nullptr); + disconnect(version.get(), &Version::typeChanged, this, nullptr); + connect(version.get(), &Version::requiresChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector() << RequiresRole); }); - connect(version.get(), &Version::timeChanged, this, - [this, row]() { emit dataChanged(index(row), index(row), QVector() << TimeRole << SortRole); }); - connect(version.get(), &Version::typeChanged, this, - [this, row]() { emit dataChanged(index(row), index(row), QVector() << TypeRole); }); + connect(version.get(), &Version::timeChanged, this, [this, row]() { + emit dataChanged(index(row), index(row), { TimeRole, SortRole }); + }); + connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), { TypeRole }); }); } BaseVersion::Ptr VersionList::getRecommended() const diff --git a/launcher/meta/VersionList.h b/launcher/meta/VersionList.h index 2c5624701..22f9a3a92 100644 --- a/launcher/meta/VersionList.h +++ b/launcher/meta/VersionList.h @@ -30,13 +30,14 @@ class VersionList : public BaseVersionList, public BaseEntity { Q_PROPERTY(QString name READ name NOTIFY nameChanged) public: explicit VersionList(const QString& uid, QObject* parent = nullptr); + virtual ~VersionList() = default; using Ptr = std::shared_ptr; enum Roles { UidRole = Qt::UserRole + 100, TimeRole, RequiresRole, VersionPtrRole }; - Task::Ptr getLoadTask() override; bool isLoaded() override; + [[nodiscard]] Task::Ptr getLoadTask() override; const BaseVersion::Ptr at(int i) const override; int count() const override; void sortVersions() override; diff --git a/launcher/minecraft/AssetsUtils.cpp b/launcher/minecraft/AssetsUtils.cpp index 6bbe0bb2c..4406d9b34 100644 --- a/launcher/minecraft/AssetsUtils.cpp +++ b/launcher/minecraft/AssetsUtils.cpp @@ -283,8 +283,7 @@ Net::NetRequest::Ptr AssetObject::getDownloadAction() if ((!objectFile.isFile()) || (objectFile.size() != size)) { auto objectDL = Net::ApiDownload::makeFile(getUrl(), objectFile.filePath()); if (hash.size()) { - auto rawHash = QByteArray::fromHex(hash.toLatin1()); - objectDL->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawHash)); + objectDL->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, hash)); } objectDL->setProgress(objectDL->getProgress(), size); return objectDL; diff --git a/launcher/minecraft/Component.cpp b/launcher/minecraft/Component.cpp index ad2e4023c..1ffcccada 100644 --- a/launcher/minecraft/Component.cpp +++ b/launcher/minecraft/Component.cpp @@ -56,18 +56,6 @@ Component::Component(PackProfile* parent, const QString& uid) m_uid = uid; } -Component::Component(PackProfile* parent, std::shared_ptr version) -{ - assert(parent); - m_parent = parent; - - m_metaVersion = version; - m_uid = version->uid(); - m_version = m_cachedVersion = version->version(); - m_cachedName = version->name(); - m_loaded = version->isLoaded(); -} - Component::Component(PackProfile* parent, const QString& uid, std::shared_ptr file) { assert(parent); @@ -103,7 +91,11 @@ std::shared_ptr Component::getVersionFile() const { if (m_metaVersion) { if (!m_metaVersion->isLoaded()) { - m_metaVersion->load(Net::Mode::Online); + QEventLoop ev; + auto task = APPLICATION->metadataIndex()->loadVersion(m_metaVersion->uid(), m_metaVersion->version(), Net::Mode::Online); + connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); + task->start(); + ev.exec(); } return m_metaVersion->data(); } else { @@ -228,7 +220,11 @@ bool Component::isVersionChangeable() auto list = getVersionList(); if (list) { if (!list->isLoaded()) { - list->load(Net::Mode::Online); + QEventLoop ev; + auto task = list->getLoadTask(); + connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); + task->start(); + ev.exec(); } return list->count() != 0; } diff --git a/launcher/minecraft/Component.h b/launcher/minecraft/Component.h index fdb61c45e..8aa6b4743 100644 --- a/launcher/minecraft/Component.h +++ b/launcher/minecraft/Component.h @@ -22,7 +22,6 @@ class Component : public QObject, public ProblemProvider { Component(PackProfile* parent, const QString& uid); // DEPRECATED: remove these constructors? - Component(PackProfile* parent, std::shared_ptr version); Component(PackProfile* parent, const QString& uid, std::shared_ptr file); virtual ~Component() {} diff --git a/launcher/minecraft/ComponentUpdateTask.cpp b/launcher/minecraft/ComponentUpdateTask.cpp index bb838043a..1368ca5e3 100644 --- a/launcher/minecraft/ComponentUpdateTask.cpp +++ b/launcher/minecraft/ComponentUpdateTask.cpp @@ -93,9 +93,9 @@ static LoadResult loadComponent(ComponentPtr component, Task::Ptr& loadTask, Net component->m_loaded = true; result = LoadResult::LoadedLocal; } else { - metaVersion->load(netmode); - loadTask = metaVersion->getCurrentTask(); - if (loadTask) + loadTask = APPLICATION->metadataIndex()->loadVersion(component->m_uid, component->m_version, netmode); + loadTask->start(); + if (netmode == Net::Mode::Online) result = LoadResult::RequiresRemote; else if (metaVersion->isLoaded()) result = LoadResult::LoadedLocal; @@ -133,21 +133,6 @@ static LoadResult loadPackProfile(ComponentPtr component, Task::Ptr& loadTask, N } */ -static LoadResult loadIndex(Task::Ptr& loadTask, Net::Mode netmode) -{ - // FIXME: DECIDE. do we want to run the update task anyway? - if (APPLICATION->metadataIndex()->isLoaded()) { - qDebug() << "Index is already loaded"; - return LoadResult::LoadedLocal; - } - APPLICATION->metadataIndex()->load(netmode); - loadTask = APPLICATION->metadataIndex()->getCurrentTask(); - if (loadTask) { - return LoadResult::RequiresRemote; - } - // FIXME: this is assuming the load succeeded... did it really? - return LoadResult::LoadedLocal; -} } // namespace void ComponentUpdateTask::loadComponents() @@ -156,23 +141,8 @@ void ComponentUpdateTask::loadComponents() size_t taskIndex = 0; size_t componentIndex = 0; d->remoteLoadSuccessful = true; - // load the main index (it is needed to determine if components can revert) - { - // FIXME: tear out as a method? or lambda? - Task::Ptr indexLoadTask; - auto singleResult = loadIndex(indexLoadTask, d->netmode); - result = composeLoadResult(result, singleResult); - if (indexLoadTask) { - qDebug() << "Remote loading is being run for metadata index"; - RemoteLoadStatus status; - status.type = RemoteLoadStatus::Type::Index; - d->remoteLoadStatusList.append(status); - connect(indexLoadTask.get(), &Task::succeeded, [=]() { remoteLoadSucceeded(taskIndex); }); - connect(indexLoadTask.get(), &Task::failed, [=](const QString& error) { remoteLoadFailed(taskIndex, error); }); - connect(indexLoadTask.get(), &Task::aborted, [=]() { remoteLoadFailed(taskIndex, tr("Aborted")); }); - taskIndex++; - } - } + + m_load_tasks.clear(); // load all the components OR their lists... for (auto component : d->m_list->d->components) { Task::Ptr loadTask; @@ -205,6 +175,7 @@ void ComponentUpdateTask::loadComponents() } result = composeLoadResult(result, singleResult); if (loadTask) { + m_load_tasks.append(loadTask); qDebug() << "Remote loading is being run for" << component->getName(); connect(loadTask.get(), &Task::succeeded, [=]() { remoteLoadSucceeded(taskIndex); }); connect(loadTask.get(), &Task::failed, [=](const QString& error) { remoteLoadFailed(taskIndex, error); }); diff --git a/launcher/minecraft/ComponentUpdateTask.h b/launcher/minecraft/ComponentUpdateTask.h index 2f396a049..f225364cf 100644 --- a/launcher/minecraft/ComponentUpdateTask.h +++ b/launcher/minecraft/ComponentUpdateTask.h @@ -29,4 +29,5 @@ class ComponentUpdateTask : public Task { private: std::unique_ptr d; + QList m_load_tasks; }; diff --git a/launcher/minecraft/Library.cpp b/launcher/minecraft/Library.cpp index 4e30f72d1..c6b65bcb4 100644 --- a/launcher/minecraft/Library.cpp +++ b/launcher/minecraft/Library.cpp @@ -116,9 +116,8 @@ QList Library::getDownloads(const RuntimeContext& runtimeC options |= Net::Download::Option::MakeEternal; if (sha1.size()) { - auto rawSha1 = QByteArray::fromHex(sha1.toLatin1()); auto dl = Net::ApiDownload::makeCached(url, entry, options); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, sha1)); qDebug() << "Checksummed Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url; out.append(dl); } else { diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp index 8af014996..8add02d84 100644 --- a/launcher/minecraft/update/AssetUpdateTask.cpp +++ b/launcher/minecraft/update/AssetUpdateTask.cpp @@ -32,8 +32,7 @@ void AssetUpdateTask::executeTask() auto hexSha1 = assets->sha1.toLatin1(); qDebug() << "Asset index SHA1:" << hexSha1; auto dl = Net::ApiDownload::makeCached(indexUrl, entry); - auto rawSha1 = QByteArray::fromHex(assets->sha1.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, assets->sha1)); job->addNetAction(dl); downloadJob.reset(job); diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index a7721673e..9ceb1e3d2 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -36,6 +36,7 @@ #include "ATLPackInstallTask.h" +#include #include #include @@ -344,7 +345,11 @@ QString PackInstallTask::getVersionForLoader(QString uid) } if (!vlist->isLoaded()) { - vlist->load(Net::Mode::Online); + QEventLoop ev; + auto task = vlist->getLoadTask(); + connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); + task->start(); + ev.exec(); } if (m_version.loader.recommended || m_version.loader.latest) { @@ -638,8 +643,7 @@ void PackInstallTask::installConfigs() auto dl = Net::ApiDownload::makeCached(url, entry); if (!m_version.configs.sha1.isEmpty()) { - auto rawSha1 = QByteArray::fromHex(m_version.configs.sha1.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, m_version.configs.sha1)); } jobPtr->addNetAction(dl); archivePath = entry->getFullPath(); @@ -758,8 +762,7 @@ void PackInstallTask::downloadMods() auto dl = Net::ApiDownload::makeCached(url, entry); if (!mod.md5.isEmpty()) { - auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, mod.md5)); } jobPtr->addNetAction(dl); } else if (mod.type == ModType::Decomp) { @@ -769,8 +772,7 @@ void PackInstallTask::downloadMods() auto dl = Net::ApiDownload::makeCached(url, entry); if (!mod.md5.isEmpty()) { - auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, mod.md5)); } jobPtr->addNetAction(dl); } else { @@ -783,8 +785,7 @@ void PackInstallTask::downloadMods() auto dl = Net::ApiDownload::makeCached(url, entry); if (!mod.md5.isEmpty()) { - auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, mod.md5)); } jobPtr->addNetAction(dl); @@ -1075,36 +1076,13 @@ void PackInstallTask::install() static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version) { - auto vlist = APPLICATION->metadataIndex()->get(uid); - if (!vlist) - return {}; + QEventLoop ev; + auto task = APPLICATION->metadataIndex()->loadVersion(uid, version); + QObject::connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); + task->start(); + ev.exec(); - if (!vlist->isLoaded()) { - QEventLoop loadVersionLoop; - auto task = vlist->getLoadTask(); - QObject::connect(task.get(), &Task::finished, &loadVersionLoop, &QEventLoop::quit); - if (!task->isRunning()) - task->start(); - - loadVersionLoop.exec(); - } - - auto ver = vlist->getVersion(version); - if (!ver) - return {}; - - if (!ver->isLoaded()) { - QEventLoop loadVersionLoop; - ver->load(Net::Mode::Online); - auto task = ver->getCurrentTask(); - QObject::connect(task.get(), &Task::finished, &loadVersionLoop, &QEventLoop::quit); - if (!task->isRunning()) - task->start(); - - loadVersionLoop.exec(); - } - - return ver; + return APPLICATION->metadataIndex()->get(uid, version); } } // namespace ATLauncher diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 11bc3553b..d661f1f05 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -246,7 +246,7 @@ void FlamePackExportTask::makeApiRequest() pendingHashes.clear(); getProjectsInfo(); }); - connect(task.get(), &NetJob::failed, this, &FlamePackExportTask::getProjectsInfo); + connect(task.get(), &Task::failed, this, &FlamePackExportTask::getProjectsInfo); task->start(); } diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index ef0a3df16..b7c2757e5 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -18,6 +18,7 @@ #include "ModrinthPackExportTask.h" +#include #include #include #include @@ -28,6 +29,7 @@ #include "minecraft/mod/MetadataHandler.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/helpers/HashUtils.h" +#include "tasks/Task.h" const QStringList ModrinthPackExportTask::PREFIXES({ "mods/", "coremods/", "resourcepacks/", "texturepacks/", "shaderpacks/" }); const QStringList ModrinthPackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" }); @@ -154,8 +156,8 @@ void ModrinthPackExportTask::makeApiRequest() setStatus(tr("Finding versions for hashes...")); auto response = std::make_shared(); task = api.currentVersions(pendingHashes.values(), "sha512", response); - connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); - connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); + connect(task.get(), &Task::succeeded, [this, response]() { parseApiResponse(response); }); + connect(task.get(), &Task::failed, this, &ModrinthPackExportTask::emitFailed); task->start(); } } diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp index ed8b0a8a4..ffda05ee9 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.cpp +++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp @@ -114,8 +114,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded() auto dl = Net::ApiDownload::makeFile(mod.url, path); if (!mod.md5.isEmpty()) { - auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, mod.md5)); } m_filesNetJob->addNetAction(dl); diff --git a/launcher/net/ChecksumValidator.h b/launcher/net/ChecksumValidator.h index 34ee5f856..7e01153c6 100644 --- a/launcher/net/ChecksumValidator.h +++ b/launcher/net/ChecksumValidator.h @@ -43,6 +43,9 @@ namespace Net { class ChecksumValidator : public Validator { public: + ChecksumValidator(QCryptographicHash::Algorithm algorithm, QString expectedHex) + : Net::ChecksumValidator(algorithm, QByteArray::fromHex(expectedHex.toLatin1())) + {} ChecksumValidator(QCryptographicHash::Algorithm algorithm, QByteArray expected = QByteArray()) : m_checksum(algorithm), m_expected(expected) {}; virtual ~ChecksumValidator() = default; diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 56ade8e32..7fc1e46ac 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -591,8 +591,7 @@ void TranslationsModel::downloadTranslation(QString key) entry->setStale(true); auto dl = Net::Download::makeCached(QUrl(BuildConfig.TRANSLATIONS_BASE_URL + lang->file_name), entry); - auto rawHash = QByteArray::fromHex(lang->file_sha1.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawHash)); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, lang->file_sha1)); dl->setProgress(dl->getProgress(), lang->file_size); d->m_dl_job.reset(new NetJob("Translation for " + key, APPLICATION->network())); diff --git a/launcher/ui/pages/instance/VersionPage.h b/launcher/ui/pages/instance/VersionPage.h index 951643743..602d09206 100644 --- a/launcher/ui/pages/instance/VersionPage.h +++ b/launcher/ui/pages/instance/VersionPage.h @@ -41,6 +41,7 @@ #pragma once #include +#include #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" diff --git a/launcher/ui/pages/modplatform/TexturePackModel.cpp b/launcher/ui/pages/modplatform/TexturePackModel.cpp index fa6369514..cb4cafd41 100644 --- a/launcher/ui/pages/modplatform/TexturePackModel.cpp +++ b/launcher/ui/pages/modplatform/TexturePackModel.cpp @@ -17,9 +17,9 @@ TexturePackResourceModel::TexturePackResourceModel(BaseInstance const& inst, Res { if (!m_version_list->isLoaded()) { qDebug() << "Loading version list..."; - auto task = m_version_list->getLoadTask(); - if (!task->isRunning()) - task->start(); + m_task = m_version_list->getLoadTask(); + if (!m_task->isRunning()) + m_task->start(); } } @@ -35,7 +35,8 @@ void waitOnVersionListLoad(Meta::VersionList::Ptr version_list) auto task = version_list->getLoadTask(); QObject::connect(task.get(), &Task::finished, &load_version_list_loop, &QEventLoop::quit); - + if (!task->isRunning()) + task->start(); load_version_list_loop.exec(); if (time_limit_for_list_load.isActive()) time_limit_for_list_load.stop(); diff --git a/launcher/ui/pages/modplatform/TexturePackModel.h b/launcher/ui/pages/modplatform/TexturePackModel.h index bb2db5cfc..607a03be3 100644 --- a/launcher/ui/pages/modplatform/TexturePackModel.h +++ b/launcher/ui/pages/modplatform/TexturePackModel.h @@ -22,6 +22,7 @@ class TexturePackResourceModel : public ResourcePackResourceModel { protected: Meta::VersionList::Ptr m_version_list; + Task::Ptr m_task; }; } // namespace ResourceDownload diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index a24630b31..1a62e689b 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -129,16 +129,12 @@ void VersionSelectWidget::closeEvent(QCloseEvent* event) void VersionSelectWidget::loadList() { - auto newTask = m_vlist->getLoadTask(); - if (!newTask) { - return; - } - loadTask = newTask.get(); - connect(loadTask, &Task::succeeded, this, &VersionSelectWidget::onTaskSucceeded); - connect(loadTask, &Task::failed, this, &VersionSelectWidget::onTaskFailed); - connect(loadTask, &Task::progress, this, &VersionSelectWidget::changeProgress); - if (!loadTask->isRunning()) { - loadTask->start(); + m_load_task = m_vlist->getLoadTask(); + connect(m_load_task.get(), &Task::succeeded, this, &VersionSelectWidget::onTaskSucceeded); + connect(m_load_task.get(), &Task::failed, this, &VersionSelectWidget::onTaskFailed); + connect(m_load_task.get(), &Task::progress, this, &VersionSelectWidget::changeProgress); + if (!m_load_task->isRunning()) { + m_load_task->start(); } sneakyProgressBar->setHidden(false); } @@ -150,7 +146,7 @@ void VersionSelectWidget::onTaskSucceeded() } sneakyProgressBar->setHidden(true); preselect(); - loadTask = nullptr; + m_load_task.reset(); } void VersionSelectWidget::onTaskFailed(const QString& reason) diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index d5ef1cc9f..d8d8506ea 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -98,7 +98,7 @@ class VersionSelectWidget : public QWidget { BaseVersionList* m_vlist = nullptr; VersionProxyModel* m_proxyModel = nullptr; int resizeOnColumn = 0; - Task* loadTask; + Task::Ptr m_load_task; bool preselectedAlready = false; QVBoxLayout* verticalLayout = nullptr; From 06e1cab41f4afa473a10d39d2986b3c509454054 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 22 Jun 2024 12:33:32 +0300 Subject: [PATCH 085/120] force online in case the offline load failed Signed-off-by: Trial97 --- launcher/meta/BaseEntity.cpp | 5 ++++- launcher/minecraft/ComponentUpdateTask.cpp | 24 +++++++++++++++++----- launcher/minecraft/ComponentUpdateTask.h | 1 - launcher/minecraft/ComponentUpdateTask_p.h | 2 ++ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 581eaa7f4..5079ef5b9 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -122,7 +122,10 @@ void BaseEntityLoadTask::executeTask() } } // if we need remote update, run the update task - if (m_mode == Net::Mode::Offline || (!m_entity->m_sha256.isEmpty() && m_entity->m_sha256 == m_entity->m_file_sha256)) { + auto hashMatches = !m_entity->m_sha256.isEmpty() && m_entity->m_sha256 == m_entity->m_file_sha256; + auto wasLoadedOffline = m_entity->m_load_status != BaseEntity::LoadStatus::NotLoaded && m_mode == Net::Mode::Offline; + if (wasLoadedOffline || hashMatches) { + m_entity->m_load_status = BaseEntity::LoadStatus::Local; emitSucceeded(); return; } diff --git a/launcher/minecraft/ComponentUpdateTask.cpp b/launcher/minecraft/ComponentUpdateTask.cpp index 1368ca5e3..4d205af6c 100644 --- a/launcher/minecraft/ComponentUpdateTask.cpp +++ b/launcher/minecraft/ComponentUpdateTask.cpp @@ -13,6 +13,7 @@ #include "net/Mode.h" #include "Application.h" +#include "tasks/Task.h" /* * This is responsible for loading the components of a component list AND resolving dependency issues between them @@ -142,7 +143,6 @@ void ComponentUpdateTask::loadComponents() size_t componentIndex = 0; d->remoteLoadSuccessful = true; - m_load_tasks.clear(); // load all the components OR their lists... for (auto component : d->m_list->d->components) { Task::Ptr loadTask; @@ -175,14 +175,14 @@ void ComponentUpdateTask::loadComponents() } result = composeLoadResult(result, singleResult); if (loadTask) { - m_load_tasks.append(loadTask); qDebug() << "Remote loading is being run for" << component->getName(); - connect(loadTask.get(), &Task::succeeded, [=]() { remoteLoadSucceeded(taskIndex); }); - connect(loadTask.get(), &Task::failed, [=](const QString& error) { remoteLoadFailed(taskIndex, error); }); - connect(loadTask.get(), &Task::aborted, [=]() { remoteLoadFailed(taskIndex, tr("Aborted")); }); + connect(loadTask.get(), &Task::succeeded, this, [this, taskIndex]() { remoteLoadSucceeded(taskIndex); }); + connect(loadTask.get(), &Task::failed, this, [this, taskIndex](const QString& error) { remoteLoadFailed(taskIndex, error); }); + connect(loadTask.get(), &Task::aborted, this, [this, taskIndex]() { remoteLoadFailed(taskIndex, tr("Aborted")); }); RemoteLoadStatus status; status.type = loadType; status.PackProfileIndex = componentIndex; + status.task = loadTask; d->remoteLoadStatusList.append(status); taskIndex++; } @@ -489,7 +489,14 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly) void ComponentUpdateTask::remoteLoadSucceeded(size_t taskIndex) { + if (static_cast(d->remoteLoadStatusList.size()) < taskIndex) { + qWarning() << "Got task index outside of results" << taskIndex; + return; + } auto& taskSlot = d->remoteLoadStatusList[taskIndex]; + disconnect(taskSlot.task.get(), &Task::succeeded, this, nullptr); + disconnect(taskSlot.task.get(), &Task::failed, this, nullptr); + disconnect(taskSlot.task.get(), &Task::aborted, this, nullptr); if (taskSlot.finished) { qWarning() << "Got multiple results from remote load task" << taskIndex; return; @@ -509,7 +516,14 @@ void ComponentUpdateTask::remoteLoadSucceeded(size_t taskIndex) void ComponentUpdateTask::remoteLoadFailed(size_t taskIndex, const QString& msg) { + if (static_cast(d->remoteLoadStatusList.size()) < taskIndex) { + qWarning() << "Got task index outside of results" << taskIndex; + return; + } auto& taskSlot = d->remoteLoadStatusList[taskIndex]; + disconnect(taskSlot.task.get(), &Task::succeeded, this, nullptr); + disconnect(taskSlot.task.get(), &Task::failed, this, nullptr); + disconnect(taskSlot.task.get(), &Task::aborted, this, nullptr); if (taskSlot.finished) { qWarning() << "Got multiple results from remote load task" << taskIndex; return; diff --git a/launcher/minecraft/ComponentUpdateTask.h b/launcher/minecraft/ComponentUpdateTask.h index f225364cf..2f396a049 100644 --- a/launcher/minecraft/ComponentUpdateTask.h +++ b/launcher/minecraft/ComponentUpdateTask.h @@ -29,5 +29,4 @@ class ComponentUpdateTask : public Task { private: std::unique_ptr d; - QList m_load_tasks; }; diff --git a/launcher/minecraft/ComponentUpdateTask_p.h b/launcher/minecraft/ComponentUpdateTask_p.h index 00e8f2fbe..b82553700 100644 --- a/launcher/minecraft/ComponentUpdateTask_p.h +++ b/launcher/minecraft/ComponentUpdateTask_p.h @@ -4,6 +4,7 @@ #include #include #include "net/Mode.h" +#include "tasks/Task.h" class PackProfile; @@ -13,6 +14,7 @@ struct RemoteLoadStatus { bool finished = false; bool succeeded = false; QString error; + Task::Ptr task; }; struct ComponentUpdateTaskData { From 0a95b57c0a724bf1739c86fe8067502c55a2caea Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 22 Jun 2024 12:48:55 +0300 Subject: [PATCH 086/120] moved QEventLoops inside functions Signed-off-by: Trial97 --- launcher/meta/Index.cpp | 10 ++++++++++ launcher/meta/Index.h | 3 +++ launcher/meta/VersionList.cpp | 10 ++++++++++ launcher/meta/VersionList.h | 3 +++ launcher/minecraft/Component.cpp | 19 +++++++------------ .../atlauncher/ATLPackInstallTask.cpp | 17 ++--------------- 6 files changed, 35 insertions(+), 27 deletions(-) diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index ddcebc453..bd0745b6b 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -149,4 +149,14 @@ Task::Ptr Index::loadVersion(const QString& uid, const QString& version, Net::Mo loadTask->addTask(versionList->getVersion(version)->loadTask(mode)); return loadTask; } + +Version::Ptr Index::getLoadedVersion(const QString& uid, const QString& version) +{ + QEventLoop ev; + auto task = loadVersion(uid, version); + QObject::connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); + task->start(); + ev.exec(); + return get(uid, version); +} } // namespace Meta diff --git a/launcher/meta/Index.h b/launcher/meta/Index.h index e54cdd88b..026a00c07 100644 --- a/launcher/meta/Index.h +++ b/launcher/meta/Index.h @@ -50,6 +50,9 @@ class Index : public QAbstractListModel, public BaseEntity { Task::Ptr loadVersion(const QString& uid, const QString& version = {}, Net::Mode mode = Net::Mode::Online, bool force = false); + // this blocks until the version is loaded + Version::Ptr getLoadedVersion(const QString& uid, const QString& version); + public: // for usage by parsers only void merge(const std::shared_ptr& other); diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index f7269c57f..45acc5d00 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -254,4 +254,14 @@ BaseVersion::Ptr VersionList::getRecommended() const return m_recommended; } +void VersionList::waitToLoad() +{ + if (isLoaded()) + return; + QEventLoop ev; + auto task = getLoadTask(); + QObject::connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); + task->start(); + ev.exec(); +} } // namespace Meta diff --git a/launcher/meta/VersionList.h b/launcher/meta/VersionList.h index 22f9a3a92..90e0c8e5e 100644 --- a/launcher/meta/VersionList.h +++ b/launcher/meta/VersionList.h @@ -59,6 +59,9 @@ class VersionList : public BaseVersionList, public BaseEntity { QVector versions() const { return m_versions; } + // this blocks until the version list is loaded + void waitToLoad(); + public: // for usage only by parsers void setName(const QString& name); void setVersions(const QVector& versions); diff --git a/launcher/minecraft/Component.cpp b/launcher/minecraft/Component.cpp index 1ffcccada..9594d9a73 100644 --- a/launcher/minecraft/Component.cpp +++ b/launcher/minecraft/Component.cpp @@ -91,11 +91,8 @@ std::shared_ptr Component::getVersionFile() const { if (m_metaVersion) { if (!m_metaVersion->isLoaded()) { - QEventLoop ev; - auto task = APPLICATION->metadataIndex()->loadVersion(m_metaVersion->uid(), m_metaVersion->version(), Net::Mode::Online); - connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); - task->start(); - ev.exec(); + // this method is const but the loading of meta changes the information + APPLICATION->metadataIndex()->getLoadedVersion(m_metaVersion->uid(), m_metaVersion->version()); } return m_metaVersion->data(); } else { @@ -197,10 +194,12 @@ bool Component::isCustomizable() } return false; } + bool Component::isRemovable() { return !m_important; } + bool Component::isRevertible() { if (isCustom()) { @@ -210,22 +209,18 @@ bool Component::isRevertible() } return false; } + bool Component::isMoveable() { // HACK, FIXME: this was too dumb and wouldn't follow dependency constraints anyway. For now hardcoded to 'true'. return true; } + bool Component::isVersionChangeable() { auto list = getVersionList(); if (list) { - if (!list->isLoaded()) { - QEventLoop ev; - auto task = list->getLoadTask(); - connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); - task->start(); - ev.exec(); - } + list->waitToLoad(); return list->count() != 0; } return false; diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 9ceb1e3d2..abe7d0177 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -36,7 +36,6 @@ #include "ATLPackInstallTask.h" -#include #include #include @@ -344,13 +343,7 @@ QString PackInstallTask::getVersionForLoader(QString uid) return Q_NULLPTR; } - if (!vlist->isLoaded()) { - QEventLoop ev; - auto task = vlist->getLoadTask(); - connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); - task->start(); - ev.exec(); - } + vlist->waitToLoad(); if (m_version.loader.recommended || m_version.loader.latest) { for (int i = 0; i < vlist->versions().size(); i++) { @@ -1076,13 +1069,7 @@ void PackInstallTask::install() static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version) { - QEventLoop ev; - auto task = APPLICATION->metadataIndex()->loadVersion(uid, version); - QObject::connect(task.get(), &Task::finished, &ev, &QEventLoop::quit); - task->start(); - ev.exec(); - - return APPLICATION->metadataIndex()->get(uid, version); + return APPLICATION->metadataIndex()->getLoadedVersion(uid, version); } } // namespace ATLauncher From 715c99636da442e6c8abafc7146a7563c919d98d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 23 Jun 2024 01:47:49 +0300 Subject: [PATCH 087/120] fix offline mode for meta Signed-off-by: Trial97 --- launcher/meta/BaseEntity.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 5079ef5b9..6c064c99a 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -102,7 +102,7 @@ void BaseEntityLoadTask::executeTask() { const QString fname = QDir("meta").absoluteFilePath(m_entity->localFilename()); // load local file if nothing is loaded yet - if (m_entity->m_load_status != BaseEntity::LoadStatus::NotLoaded && QFile::exists(fname)) { + if (m_entity->m_load_status == BaseEntity::LoadStatus::NotLoaded && QFile::exists(fname)) { setStatus(tr("Loading local file")); try { auto fileData = FS::read(fname); @@ -125,7 +125,6 @@ void BaseEntityLoadTask::executeTask() auto hashMatches = !m_entity->m_sha256.isEmpty() && m_entity->m_sha256 == m_entity->m_file_sha256; auto wasLoadedOffline = m_entity->m_load_status != BaseEntity::LoadStatus::NotLoaded && m_mode == Net::Mode::Offline; if (wasLoadedOffline || hashMatches) { - m_entity->m_load_status = BaseEntity::LoadStatus::Local; emitSucceeded(); return; } @@ -142,6 +141,7 @@ void BaseEntityLoadTask::executeTask() dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Algorithm::Sha256, m_entity->m_sha256)); dl->addValidator(new ParsingValidator(m_entity)); m_task->addNetAction(dl); + m_task->setAskRetry(false); connect(m_task.get(), &Task::failed, this, &BaseEntityLoadTask::emitFailed); connect(m_task.get(), &Task::succeeded, this, &BaseEntityLoadTask::emitSucceeded); connect(m_task.get(), &Task::succeeded, this, [this]() { From cf220356b15af613fc06d981d61eb697f7f87ea0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 26 Jun 2024 08:56:17 +0300 Subject: [PATCH 088/120] fixed panic with recursive eventloop Signed-off-by: Trial97 --- launcher/minecraft/Component.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/launcher/minecraft/Component.cpp b/launcher/minecraft/Component.cpp index 9594d9a73..32a1deb68 100644 --- a/launcher/minecraft/Component.cpp +++ b/launcher/minecraft/Component.cpp @@ -90,10 +90,6 @@ void Component::applyTo(LaunchProfile* profile) std::shared_ptr Component::getVersionFile() const { if (m_metaVersion) { - if (!m_metaVersion->isLoaded()) { - // this method is const but the loading of meta changes the information - APPLICATION->metadataIndex()->getLoadedVersion(m_metaVersion->uid(), m_metaVersion->version()); - } return m_metaVersion->data(); } else { return m_file; @@ -120,29 +116,35 @@ int Component::getOrder() } return 0; } + void Component::setOrder(int order) { m_orderOverride = true; m_order = order; } + QString Component::getID() { return m_uid; } + QString Component::getName() { if (!m_cachedName.isEmpty()) return m_cachedName; return m_uid; } + QString Component::getVersion() { return m_cachedVersion; } + QString Component::getFilename() { return m_parent->patchFilePathForUid(m_uid); } + QDateTime Component::getReleaseDateTime() { if (m_metaVersion) { @@ -187,12 +189,7 @@ bool Component::isCustom() bool Component::isCustomizable() { - if (m_metaVersion) { - if (getVersionFile()) { - return true; - } - } - return false; + return m_metaVersion && getVersionFile(); } bool Component::isRemovable() From 9d903175ab77fad96281b0f29ed29cf7b6c10c16 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 28 Jun 2024 20:51:52 +0300 Subject: [PATCH 089/120] format Signed-off-by: Trial97 --- launcher/meta/BaseEntity.cpp | 2 +- launcher/meta/VersionList.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 6c064c99a..a8350eaeb 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -32,7 +32,7 @@ namespace Meta { class ParsingValidator : public Net::Validator { public: /* con/des */ - ParsingValidator(BaseEntity* entity) : m_entity(entity){}; + ParsingValidator(BaseEntity* entity) : m_entity(entity) {}; virtual ~ParsingValidator() = default; public: /* methods */ diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index 45acc5d00..f21e4594a 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -243,9 +243,8 @@ void VersionList::setupAddedVersion(const int row, const Version::Ptr& version) connect(version.get(), &Version::requiresChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector() << RequiresRole); }); - connect(version.get(), &Version::timeChanged, this, [this, row]() { - emit dataChanged(index(row), index(row), { TimeRole, SortRole }); - }); + connect(version.get(), &Version::timeChanged, this, + [this, row]() { emit dataChanged(index(row), index(row), { TimeRole, SortRole }); }); connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), { TypeRole }); }); } From 63a458ca0c9dbad02dd4218c9eed35bb9af7b6e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 28 Jun 2024 21:48:40 +0000 Subject: [PATCH 090/120] Update DeterminateSystems/update-flake-lock action to v23 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 2226d0710..e1ab2e86e 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - - uses: DeterminateSystems/update-flake-lock@v22 + - uses: DeterminateSystems/update-flake-lock@v23 with: commit-msg: "chore(nix): update lockfile" pr-title: "chore(nix): update lockfile" From b989c5a36cdc4f8b1555c5bacb7e28e897f19cf0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 10 Jul 2024 16:24:31 +0300 Subject: [PATCH 091/120] refactor MinecraftUpdate Task Signed-off-by: Trial97 --- launcher/minecraft/MinecraftUpdate.cpp | 125 ++----------------------- launcher/minecraft/MinecraftUpdate.h | 32 +------ 2 files changed, 13 insertions(+), 144 deletions(-) diff --git a/launcher/minecraft/MinecraftUpdate.cpp b/launcher/minecraft/MinecraftUpdate.cpp index c009317a6..b63430aa8 100644 --- a/launcher/minecraft/MinecraftUpdate.cpp +++ b/launcher/minecraft/MinecraftUpdate.cpp @@ -16,32 +16,22 @@ #include "MinecraftUpdate.h" #include "MinecraftInstance.h" -#include -#include -#include -#include - -#include -#include "BaseInstance.h" -#include "minecraft/Library.h" #include "minecraft/PackProfile.h" +#include "tasks/SequentialTask.h" #include "update/AssetUpdateTask.h" #include "update/FMLLibrariesTask.h" #include "update/FoldersTask.h" #include "update/LibrariesTask.h" -#include -#include - -MinecraftUpdate::MinecraftUpdate(MinecraftInstance* inst, QObject* parent) : Task(parent), m_inst(inst) {} +MinecraftUpdate::MinecraftUpdate(MinecraftInstance* inst, QObject* parent) : SequentialTask(parent), m_inst(inst) {} void MinecraftUpdate::executeTask() { - m_tasks.clear(); + m_queue.clear(); // create folders { - m_tasks.append(makeShared(m_inst)); + addTask(makeShared(m_inst)); } // add metadata update task if necessary @@ -50,121 +40,24 @@ void MinecraftUpdate::executeTask() components->reload(Net::Mode::Online); auto task = components->getCurrentTask(); if (task) { - m_tasks.append(task); + addTask(task); } } // libraries download { - m_tasks.append(makeShared(m_inst)); + addTask(makeShared(m_inst)); } // FML libraries download and copy into the instance { - m_tasks.append(makeShared(m_inst)); + addTask(makeShared(m_inst)); } // assets update { - m_tasks.append(makeShared(m_inst)); + addTask(makeShared(m_inst)); } - if (!m_preFailure.isEmpty()) { - emitFailed(m_preFailure); - return; - } - next(); -} - -void MinecraftUpdate::next() -{ - if (m_abort) { - emitFailed(tr("Aborted by user.")); - return; - } - if (m_failed_out_of_order) { - emitFailed(m_fail_reason); - return; - } - m_currentTask++; - if (m_currentTask > 0) { - auto task = m_tasks[m_currentTask - 1]; - disconnect(task.get(), &Task::succeeded, this, &MinecraftUpdate::subtaskSucceeded); - disconnect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed); - disconnect(task.get(), &Task::aborted, this, &Task::abort); - disconnect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); - disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress); - disconnect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); - disconnect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); - } - if (m_currentTask == m_tasks.size()) { - emitSucceeded(); - return; - } - auto task = m_tasks[m_currentTask]; - // if the task is already finished by the time we look at it, skip it - if (task->isFinished()) { - qCritical() << "MinecraftUpdate: Skipping finished subtask" << m_currentTask << ":" << task.get(); - next(); - } - connect(task.get(), &Task::succeeded, this, &MinecraftUpdate::subtaskSucceeded); - connect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed); - connect(task.get(), &Task::aborted, this, &Task::abort); - connect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); - connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress); - connect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); - connect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); - // if the task is already running, do not start it again - if (!task->isRunning()) { - task->start(); - } -} - -void MinecraftUpdate::subtaskSucceeded() -{ - if (isFinished()) { - qCritical() << "MinecraftUpdate: Subtask" << sender() << "succeeded, but work was already done!"; - return; - } - auto senderTask = QObject::sender(); - auto currentTask = m_tasks[m_currentTask].get(); - if (senderTask != currentTask) { - qDebug() << "MinecraftUpdate: Subtask" << sender() << "succeeded out of order."; - return; - } - next(); -} - -void MinecraftUpdate::subtaskFailed(QString error) -{ - if (isFinished()) { - qCritical() << "MinecraftUpdate: Subtask" << sender() << "failed, but work was already done!"; - return; - } - auto senderTask = QObject::sender(); - auto currentTask = m_tasks[m_currentTask].get(); - if (senderTask != currentTask) { - qDebug() << "MinecraftUpdate: Subtask" << sender() << "failed out of order."; - m_failed_out_of_order = true; - m_fail_reason = error; - return; - } - emitFailed(error); -} - -bool MinecraftUpdate::abort() -{ - if (!m_abort) { - m_abort = true; - auto task = m_tasks[m_currentTask]; - if (task->canAbort()) { - return task->abort(); - } - } - return true; -} - -bool MinecraftUpdate::canAbort() const -{ - return true; + SequentialTask::executeTask(); } diff --git a/launcher/minecraft/MinecraftUpdate.h b/launcher/minecraft/MinecraftUpdate.h index 591c6afcb..456a13518 100644 --- a/launcher/minecraft/MinecraftUpdate.h +++ b/launcher/minecraft/MinecraftUpdate.h @@ -15,43 +15,19 @@ #pragma once -#include -#include -#include +#include "tasks/SequentialTask.h" -#include -#include "minecraft/VersionFilterData.h" -#include "net/NetJob.h" -#include "tasks/Task.h" - -class MinecraftVersion; class MinecraftInstance; -// FIXME: This looks very similar to a SequentialTask. Maybe we can reduce code duplications? :^) - -class MinecraftUpdate : public Task { +// this needs to be a task because components->reload does stuff that may block +class MinecraftUpdate : public SequentialTask { Q_OBJECT public: explicit MinecraftUpdate(MinecraftInstance* inst, QObject* parent = 0); - virtual ~MinecraftUpdate() {}; + virtual ~MinecraftUpdate() = default; void executeTask() override; - bool canAbort() const override; - - private slots: - bool abort() override; - void subtaskSucceeded(); - void subtaskFailed(QString error); - - private: - void next(); private: MinecraftInstance* m_inst = nullptr; - QList m_tasks; - QString m_preFailure; - int m_currentTask = -1; - bool m_abort = false; - bool m_failed_out_of_order = false; - QString m_fail_reason; }; From d3ca8864c228cd1131703c2164f9ab6856136976 Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Fri, 12 Jul 2024 23:54:22 +0300 Subject: [PATCH 092/120] chore: update Qt to 6.7.2 Signed-off-by: Edgars Cirulis --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8212af233..aa6e8f64f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -79,7 +79,7 @@ jobs: qt_ver: 6 qt_host: windows qt_arch: "" - qt_version: "6.7.1" + qt_version: "6.7.2" qt_modules: "qt5compat qtimageformats qtnetworkauth" - os: windows-2022 @@ -90,7 +90,7 @@ jobs: qt_ver: 6 qt_host: windows qt_arch: "win64_msvc2019_arm64" - qt_version: "6.7.1" + qt_version: "6.7.2" qt_modules: "qt5compat qtimageformats qtnetworkauth" - os: macos-12 @@ -99,7 +99,7 @@ jobs: qt_ver: 6 qt_host: mac qt_arch: "" - qt_version: "6.7.1" + qt_version: "6.7.2" qt_modules: "qt5compat qtimageformats qtnetworkauth" - os: macos-12 From ff31e88cf8a1280c0ab93033a51832037b938883 Mon Sep 17 00:00:00 2001 From: Evan Goode Date: Sat, 20 Jul 2024 18:40:32 -0400 Subject: [PATCH 093/120] nix: sync changes from nixpkgs Brings in changes from the Prism Launcher derivation(s) in nixpkgs, notably from https://github.com/NixOS/nixpkgs/pull/321851 and https://github.com/NixOS/nixpkgs/pull/303880 Signed-off-by: Evan Goode --- nix/distribution.nix | 3 +- nix/pkg/default.nix | 107 +++++++++++++++++++------------- nix/pkg/wrapper.nix | 143 +++++++++++++++++++++++++++++-------------- 3 files changed, 160 insertions(+), 93 deletions(-) diff --git a/nix/distribution.nix b/nix/distribution.nix index d9c6784a1..28ef7ced1 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -24,9 +24,8 @@ overlays.default = final: prev: let version = builtins.substring 0 8 self.lastModifiedDate or "dirty"; in { - prismlauncher-unwrapped = prev.qt6Packages.callPackage ./pkg { + prismlauncher-unwrapped = prev.callPackage ./pkg { inherit (inputs) libnbtplusplus; - inherit ((final.darwin or prev.darwin).apple_sdk.frameworks) Cocoa; inherit version; }; diff --git a/nix/pkg/default.nix b/nix/pkg/default.nix index 1a3d8224f..f3ff3789c 100644 --- a/nix/pkg/default.nix +++ b/nix/pkg/default.nix @@ -1,27 +1,27 @@ { lib, stdenv, - canonicalize-jars-hook, cmake, cmark, - Cocoa, - ninja, - jdk17, - zlib, - qtbase, - qtnetworkauth, - quazip, + darwin, extra-cmake-modules, - tomlplusplus, - ghc_filesystem, gamemode, + ghc_filesystem, + jdk17, + kdePackages, + ninja, + stripJavaArchivesHook, + tomlplusplus, + zlib, msaClientID ? null, gamemodeSupport ? stdenv.isLinux, version, libnbtplusplus, }: -assert lib.assertMsg (stdenv.isLinux || !gamemodeSupport) "gamemodeSupport is only available on Linux"; - stdenv.mkDerivation rec { +assert lib.assertMsg ( + gamemodeSupport -> stdenv.isLinux +) "gamemodeSupport is only available on Linux."; + stdenv.mkDerivation { pname = "prismlauncher-unwrapped"; inherit version; @@ -39,49 +39,68 @@ assert lib.assertMsg (stdenv.isLinux || !gamemodeSupport) "gamemodeSupport is on ]); }; - nativeBuildInputs = [extra-cmake-modules cmake jdk17 ninja canonicalize-jars-hook]; - buildInputs = - [ - qtbase - qtnetworkauth - zlib - quazip - ghc_filesystem - tomlplusplus - cmark - ] - ++ lib.optional gamemodeSupport gamemode - ++ lib.optionals stdenv.isDarwin [Cocoa]; - - hardeningEnable = lib.optionals stdenv.isLinux ["pie"]; - - cmakeFlags = - [ - "-DLauncher_BUILD_PLATFORM=nixpkgs" - ] - ++ lib.optionals (msaClientID != null) ["-DLauncher_MSA_CLIENT_ID=${msaClientID}"] - ++ lib.optionals (lib.versionOlder qtbase.version "6") ["-DLauncher_QT_VERSION_MAJOR=5"] - ++ lib.optionals stdenv.isDarwin ["-DINSTALL_BUNDLE=nodeps" "-DMACOSX_SPARKLE_UPDATE_FEED_URL=''"]; - postUnpack = '' rm -rf source/libraries/libnbtplusplus ln -s ${libnbtplusplus} source/libraries/libnbtplusplus ''; + nativeBuildInputs = [ + cmake + ninja + extra-cmake-modules + jdk17 + stripJavaArchivesHook + ]; + + buildInputs = + [ + cmark + ghc_filesystem + kdePackages.qtbase + kdePackages.qtnetworkauth + kdePackages.quazip + tomlplusplus + zlib + ] + ++ lib.optionals stdenv.isDarwin [darwin.apple_sdk.frameworks.Cocoa] + ++ lib.optional gamemodeSupport gamemode; + + hardeningEnable = lib.optionals stdenv.isLinux ["pie"]; + + cmakeFlags = + [ + (lib.cmakeFeature "Launcher_BUILD_PLATFORM" "nixpkgs") + ] + ++ lib.optionals (msaClientID != null) [ + (lib.cmakeFeature "Launcher_MSA_CLIENT_ID" (toString msaClientID)) + ] + ++ lib.optionals (lib.versionOlder kdePackages.qtbase.version "6") [ + (lib.cmakeFeature "Launcher_QT_VERSION_MAJOR" "5") + ] + ++ lib.optionals stdenv.isDarwin [ + # we wrap our binary manually + (lib.cmakeFeature "INSTALL_BUNDLE" "nodeps") + # disable built-in updater + (lib.cmakeFeature "MACOSX_SPARKLE_UPDATE_FEED_URL" "''") + (lib.cmakeFeature "CMAKE_INSTALL_PREFIX" "${placeholder "out"}/Applications/") + ]; + dontWrapQtApps = true; - meta = with lib; { - mainProgram = "prismlauncher"; - homepage = "https://prismlauncher.org/"; - description = "A free, open source launcher for Minecraft"; + meta = { + description = "Free, open source launcher for Minecraft"; longDescription = '' Allows you to have multiple, separate instances of Minecraft (each with their own mods, texture packs, saves, etc) and helps you manage them and their associated options with a simple interface. ''; - platforms = with platforms; linux ++ darwin; - changelog = "https://github.com/PrismLauncher/PrismLauncher/releases/tag/${version}"; - license = licenses.gpl3Only; - maintainers = with maintainers; [minion3665 Scrumplex getchoo]; + homepage = "https://prismlauncher.org/"; + license = lib.licenses.gpl3Only; + maintainers = with lib.maintainers; [ + Scrumplex + getchoo + ]; + mainProgram = "prismlauncher"; + platforms = lib.platforms.linux ++ lib.platforms.darwin; }; } diff --git a/nix/pkg/wrapper.nix b/nix/pkg/wrapper.nix index 8c9c1cabc..e7516397e 100644 --- a/nix/pkg/wrapper.nix +++ b/nix/pkg/wrapper.nix @@ -3,94 +3,143 @@ stdenv, symlinkJoin, prismlauncher-unwrapped, - wrapQtAppsHook, addOpenGLRunpath, - qtbase, # needed for wrapQtAppsHook - qtsvg, - qtwayland, - xorg, - libpulseaudio, - libGL, + flite, + gamemode, glfw, - openal, + glfw-wayland-minecraft, + glxinfo, jdk8, jdk17, jdk21, - gamemode, - flite, - glxinfo, - udev, + kdePackages, + libGL, + libpulseaudio, libusb1, - msaClientID ? null, - gamemodeSupport ? stdenv.isLinux, - textToSpeechSupport ? stdenv.isLinux, - controllerSupport ? stdenv.isLinux, - jdks ? [jdk21 jdk17 jdk8], + makeWrapper, + openal, + pciutils, + udev, + vulkan-loader, + xorg, additionalLibs ? [], additionalPrograms ? [], -}: let - prismlauncherFinal = prismlauncher-unwrapped.override { - inherit msaClientID gamemodeSupport; - }; + controllerSupport ? stdenv.isLinux, + gamemodeSupport ? stdenv.isLinux, + jdks ? [ + jdk21 + jdk17 + jdk8 + ], + msaClientID ? null, + textToSpeechSupport ? stdenv.isLinux, + # Adds `glfw-wayland-minecraft` to `LD_LIBRARY_PATH` + # when launched on wayland, allowing for the game to be run natively. + # Make sure to enable "Use system installation of GLFW" in instance settings + # for this to take effect + # + # Warning: This build of glfw may be unstable, and the launcher + # itself can take slightly longer to start + withWaylandGLFW ? false, +}: +assert lib.assertMsg ( + controllerSupport -> stdenv.isLinux +) "controllerSupport only has an effect on Linux."; +assert lib.assertMsg ( + textToSpeechSupport -> stdenv.isLinux +) "textToSpeechSupport only has an effect on Linux."; +assert lib.assertMsg ( + withWaylandGLFW -> stdenv.isLinux +) "withWaylandGLFW is only available on Linux."; let + prismlauncher' = prismlauncher-unwrapped.override {inherit msaClientID gamemodeSupport;}; in symlinkJoin { - name = "prismlauncher-${prismlauncherFinal.version}"; + name = "prismlauncher-${prismlauncher'.version}"; - paths = [prismlauncherFinal]; + paths = [prismlauncher']; - nativeBuildInputs = [ - wrapQtAppsHook - ]; + nativeBuildInputs = + [kdePackages.wrapQtAppsHook] + # purposefully using a shell wrapper here for variable expansion + # see https://github.com/NixOS/nixpkgs/issues/172583 + ++ lib.optional withWaylandGLFW makeWrapper; buildInputs = [ - qtbase - qtsvg + kdePackages.qtbase + kdePackages.qtsvg ] - ++ lib.optional (lib.versionAtLeast qtbase.version "6" && stdenv.isLinux) qtwayland; + ++ lib.optional ( + lib.versionAtLeast kdePackages.qtbase.version "6" && stdenv.isLinux + ) + kdePackages.qtwayland; - postBuild = '' - wrapQtAppsHook - ''; + env = { + waylandPreExec = lib.optionalString withWaylandGLFW '' + if [ -n "$WAYLAND_DISPLAY" ]; then + export LD_LIBRARY_PATH=${lib.getLib glfw-wayland-minecraft}/lib:"$LD_LIBRARY_PATH" + fi + ''; + }; + + postBuild = + lib.optionalString withWaylandGLFW '' + qtWrapperArgs+=(--run "$waylandPreExec") + '' + + '' + wrapQtAppsHook + ''; qtWrapperArgs = let runtimeLibs = - (with xorg; [ - libX11 - libXext - libXcursor - libXrandr - libXxf86vm - ]) - ++ [ + [ # lwjgl + glfw libpulseaudio libGL - glfw openal stdenv.cc.cc.lib - # oshi - udev + vulkan-loader # VulkanMod's lwjgl + + udev # oshi + + xorg.libX11 + xorg.libXext + xorg.libXcursor + xorg.libXrandr + xorg.libXxf86vm ] - ++ lib.optional gamemodeSupport gamemode.lib ++ lib.optional textToSpeechSupport flite + ++ lib.optional gamemodeSupport gamemode.lib ++ lib.optional controllerSupport libusb1 ++ additionalLibs; runtimePrograms = [ - xorg.xrandr glxinfo + pciutils # need lspci + xorg.xrandr # needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128 ] ++ additionalPrograms; in ["--prefix PRISMLAUNCHER_JAVA_PATHS : ${lib.makeSearchPath "bin/java" jdks}"] ++ lib.optionals stdenv.isLinux [ "--set LD_LIBRARY_PATH ${addOpenGLRunpath.driverLink}/lib:${lib.makeLibraryPath runtimeLibs}" - # xorg.xrandr needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128 "--prefix PATH : ${lib.makeBinPath runtimePrograms}" ]; - inherit (prismlauncherFinal) meta; + meta = { + inherit + (prismlauncher'.meta) + description + longDescription + homepage + changelog + license + maintainers + mainProgram + platforms + ; + }; } From 5d3549a5e900cc65cecfccd49da10e28765311e4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 22 Jul 2024 09:18:20 +0300 Subject: [PATCH 094/120] Add tooltips and fix archive download task Signed-off-by: Trial97 --- launcher/java/download/ArchiveDownloadTask.cpp | 1 + launcher/ui/pages/global/JavaPage.cpp | 2 +- launcher/ui/pages/global/JavaPage.ui | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/launcher/java/download/ArchiveDownloadTask.cpp b/launcher/java/download/ArchiveDownloadTask.cpp index af5381dfc..ba1c96faf 100644 --- a/launcher/java/download/ArchiveDownloadTask.cpp +++ b/launcher/java/download/ArchiveDownloadTask.cpp @@ -124,6 +124,7 @@ void ArchiveDownloadTask::extractJava(QString input) stepProgress(*progressStep); }); m_task->start(); + return; } emitFailed(tr("Could not determine archive type!")); diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index ad37fa740..97ffa5d4d 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -264,7 +264,7 @@ void JavaPage::on_removeJavaButton_clicked() for (auto& entry : entries) { if (dcast->path.startsWith(entry.canonicalFilePath())) { auto response = CustomMessageBox::selectable(this, tr("Confirm Deletion"), - tr("You are about to remove \"%1\" java version.\n" + tr("You are about to remove the Java installation named \"%1\".\n" "Are you sure?") .arg(entry.fileName()), QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index c8f62e075..e6bbeb15a 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -253,6 +253,9 @@ + + Automatically selects the Java version that is compatible with the current Minecraft instance, based on the major version required. + Autodetect Java version @@ -299,6 +302,9 @@ false + + Automatically downloads and selects the Java version recommended by Mojang. + Auto-download Mojang Java From 0ac62f9ddf0e6ef80bcb20d2828d013e31726579 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 23 Jul 2024 01:41:41 +0300 Subject: [PATCH 095/120] Recommend java major Signed-off-by: Trial97 --- launcher/Filter.cpp | 11 ++- launcher/Filter.h | 20 +++- launcher/minecraft/MinecraftInstance.h | 2 +- launcher/minecraft/VersionFile.h | 2 +- launcher/ui/java/InstallJavaDialog.cpp | 97 ++++++++++++++++++- launcher/ui/java/InstallJavaDialog.h | 3 +- launcher/ui/pages/BasePageProvider.h | 1 - launcher/ui/pages/global/JavaPage.cpp | 2 +- .../pages/instance/InstanceSettingsPage.cpp | 2 +- launcher/ui/widgets/JavaSettingsWidget.cpp | 2 +- 10 files changed, 122 insertions(+), 20 deletions(-) diff --git a/launcher/Filter.cpp b/launcher/Filter.cpp index fc1c42344..adeb2209e 100644 --- a/launcher/Filter.cpp +++ b/launcher/Filter.cpp @@ -1,16 +1,12 @@ #include "Filter.h" -Filter::~Filter() {} - ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern) {} -ContainsFilter::~ContainsFilter() {} bool ContainsFilter::accepts(const QString& value) { return value.contains(pattern); } ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern) {} -ExactFilter::~ExactFilter() {} bool ExactFilter::accepts(const QString& value) { return value == pattern; @@ -27,10 +23,15 @@ RegexpFilter::RegexpFilter(const QString& regexp, bool invert) : invert(invert) pattern.setPattern(regexp); pattern.optimize(); } -RegexpFilter::~RegexpFilter() {} bool RegexpFilter::accepts(const QString& value) { auto match = pattern.match(value); bool matched = match.hasMatch(); return invert ? (!matched) : (matched); } + +ExactListFilter::ExactListFilter(const QStringList& pattern) : m_pattern(pattern) {} +bool ExactListFilter::accepts(const QString& value) +{ + return m_pattern.isEmpty() || m_pattern.contains(value); +} \ No newline at end of file diff --git a/launcher/Filter.h b/launcher/Filter.h index 089c844d4..a8c9c14d8 100644 --- a/launcher/Filter.h +++ b/launcher/Filter.h @@ -5,14 +5,14 @@ class Filter { public: - virtual ~Filter(); + virtual ~Filter() = default; virtual bool accepts(const QString& value) = 0; }; class ContainsFilter : public Filter { public: ContainsFilter(const QString& pattern); - virtual ~ContainsFilter(); + virtual ~ContainsFilter() = default; bool accepts(const QString& value) override; private: @@ -22,7 +22,7 @@ class ContainsFilter : public Filter { class ExactFilter : public Filter { public: ExactFilter(const QString& pattern); - virtual ~ExactFilter(); + virtual ~ExactFilter() = default; bool accepts(const QString& value) override; private: @@ -32,7 +32,7 @@ class ExactFilter : public Filter { class ExactIfPresentFilter : public Filter { public: ExactIfPresentFilter(const QString& pattern); - ~ExactIfPresentFilter() override = default; + virtual ~ExactIfPresentFilter() override = default; bool accepts(const QString& value) override; private: @@ -42,10 +42,20 @@ class ExactIfPresentFilter : public Filter { class RegexpFilter : public Filter { public: RegexpFilter(const QString& regexp, bool invert); - virtual ~RegexpFilter(); + virtual ~RegexpFilter() = default; bool accepts(const QString& value) override; private: QRegularExpression pattern; bool invert = false; }; + +class ExactListFilter : public Filter { + public: + ExactListFilter(const QStringList& pattern = {}); + virtual ~ExactListFilter() = default; + bool accepts(const QString& value) override; + + private: + const QStringList& m_pattern; +}; diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 7af0df389..730116072 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -56,7 +56,7 @@ class MinecraftInstance : public BaseInstance { Q_OBJECT public: MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir); - virtual ~MinecraftInstance() {}; + virtual ~MinecraftInstance() = default; virtual void saveNow() override; void loadSpecificSettings() override; diff --git a/launcher/minecraft/VersionFile.h b/launcher/minecraft/VersionFile.h index 85ac55426..40f49aaa4 100644 --- a/launcher/minecraft/VersionFile.h +++ b/launcher/minecraft/VersionFile.h @@ -101,7 +101,7 @@ class VersionFile : public ProblemContainer { /// Mojang: list of compatible java majors QList compatibleJavaMajors; - /// Mojang: the name of recomended java version + /// Mojang: the name of recommended java version QString compatibleJavaName; /// Mojang: type of the Minecraft version diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index 1a4b4cc58..01ec56dfd 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -18,6 +18,7 @@ #include "InstallJavaDialog.h" +#include #include #include #include @@ -27,10 +28,13 @@ #include "Application.h" #include "BaseVersionList.h" #include "FileSystem.h" +#include "Filter.h" #include "java/download/ArchiveDownloadTask.h" #include "java/download/ManifestDownloadTask.h" #include "meta/Index.h" #include "meta/VersionList.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/PackProfile.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" #include "ui/java/VersionList.h" @@ -119,6 +123,27 @@ class InstallJavaPage : public QWidget, public BasePage { majorVersionSelect->loadList(); javaVersionSelect->loadList(); } + + public slots: + void setRecommendedMajors(const QStringList& majors) + { + m_recommended_majors = majors; + recommendedFilterChanged(); + } + void setRecomend(bool recomend) + { + m_recommend = recomend; + recommendedFilterChanged(); + } + void recommendedFilterChanged() + { + if (m_recommend) { + majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, new ExactListFilter(m_recommended_majors)); + } else { + majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, new ExactListFilter()); + } + } + signals: void selectionChanged(); @@ -131,6 +156,9 @@ class InstallJavaPage : public QWidget, public BasePage { QHBoxLayout* horizontalLayout = nullptr; VersionSelectWidget* majorVersionSelect = nullptr; VersionSelectWidget* javaVersionSelect = nullptr; + + QStringList m_recommended_majors; + bool m_recommend; }; static InstallJavaPage* pageCast(BasePage* page) @@ -140,8 +168,20 @@ static InstallJavaPage* pageCast(BasePage* page) return result; } namespace Java { +QStringList getRecommendedJavaVersionsFromVersionList(Meta::VersionList::Ptr list) +{ + QStringList recommendedJavas; + for (auto ver : list->versions()) { + auto major = ver->version(); + if (major.startsWith("java")) { + major = "Java " + major.mid(4); + } + recommendedJavas.append(major); + } + return recommendedJavas; +} -InstallDialog::InstallDialog(const QString& uid, QWidget* parent) +InstallDialog::InstallDialog(const QString& uid, BaseInstance* instance, QWidget* parent) : QDialog(parent), container(new PageContainer(this, QString(), this)), buttons(new QDialogButtonBox(this)) { auto layout = new QVBoxLayout(this); @@ -150,10 +190,22 @@ InstallDialog::InstallDialog(const QString& uid, QWidget* parent) layout->addWidget(container); auto buttonLayout = new QHBoxLayout(this); + auto refreshLayout = new QHBoxLayout(this); auto refreshButton = new QPushButton(tr("&Refresh"), this); connect(refreshButton, &QPushButton::clicked, this, [this] { pageCast(container->selectedPage())->loadList(); }); - buttonLayout->addWidget(refreshButton); + refreshLayout->addWidget(refreshButton); + + auto recommendedCheckBox = new QCheckBox("Recommended", this); + recommendedCheckBox->setCheckState(Qt::CheckState::Checked); + connect(recommendedCheckBox, &QCheckBox::stateChanged, this, [this](int state) { + for (BasePage* page : container->getPages()) { + pageCast(page)->setRecomend(state == Qt::Checked); + } + }); + + refreshLayout->addWidget(recommendedCheckBox); + buttonLayout->addLayout(refreshLayout); buttons->setOrientation(Qt::Horizontal); buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); @@ -168,11 +220,49 @@ InstallDialog::InstallDialog(const QString& uid, QWidget* parent) setWindowModality(Qt::WindowModal); resize(840, 480); + QStringList recommendedJavas; + if (auto mcInst = dynamic_cast(instance); mcInst) { + auto mc = mcInst->getPackProfile()->getComponent("net.minecraft"); + if (mc) { + auto file = mc->getVersionFile(); // no need for load as it should already be loaded + if (file) { + for (auto major : file->compatibleJavaMajors) { + recommendedJavas.append(QString("Java %1").arg(major)); + } + } + } + } else { + const auto versions = APPLICATION->metadataIndex()->get("net.minecraft.java"); + if (versions) { + if (versions->isLoaded()) { + recommendedJavas = getRecommendedJavaVersionsFromVersionList(versions); + } else { + auto newTask = versions->getLoadTask(); + if (newTask) { + connect(newTask.get(), &Task::succeeded, this, [this, versions] { + auto recommendedJavas = getRecommendedJavaVersionsFromVersionList(versions); + for (BasePage* page : container->getPages()) { + pageCast(page)->setRecommendedMajors(recommendedJavas); + } + }); + if (!newTask->isRunning()) + newTask->start(); + } else { + recommendedJavas = getRecommendedJavaVersionsFromVersionList(versions); + } + } + } + } for (BasePage* page : container->getPages()) { if (page->id() == uid) container->selectPage(page->id()); - connect(pageCast(page), &InstallJavaPage::selectionChanged, this, [this] { validate(); }); + auto cast = pageCast(page); + cast->setRecomend(true); + connect(cast, &InstallJavaPage::selectionChanged, this, [this] { validate(); }); + if (!recommendedJavas.isEmpty()) { + cast->setRecommendedMajors(recommendedJavas); + } } connect(container, &PageContainer::selectedPageChanged, this, [this] { validate(); }); pageCast(container->selectedPage())->selectSearch(); @@ -243,6 +333,7 @@ void InstallDialog::done(int result) QDialog::done(result); } + } // namespace Java #include "InstallJavaDialog.moc" \ No newline at end of file diff --git a/launcher/ui/java/InstallJavaDialog.h b/launcher/ui/java/InstallJavaDialog.h index 80d010c1a..d6f879207 100644 --- a/launcher/ui/java/InstallJavaDialog.h +++ b/launcher/ui/java/InstallJavaDialog.h @@ -19,6 +19,7 @@ #pragma once #include +#include "BaseInstance.h" #include "ui/pages/BasePageProvider.h" class MinecraftInstance; @@ -31,7 +32,7 @@ class InstallDialog final : public QDialog, private BasePageProvider { Q_OBJECT public: - explicit InstallDialog(const QString& uid = QString(), QWidget* parent = nullptr); + explicit InstallDialog(const QString& uid = QString(), BaseInstance* instance = nullptr, QWidget* parent = nullptr); QList getPages() override; QString dialogTitle() override; diff --git a/launcher/ui/pages/BasePageProvider.h b/launcher/ui/pages/BasePageProvider.h index 422891e6b..ef3c1cd08 100644 --- a/launcher/ui/pages/BasePageProvider.h +++ b/launcher/ui/pages/BasePageProvider.h @@ -16,7 +16,6 @@ #pragma once #include -#include #include "ui/pages/BasePage.h" class BasePageProvider { diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 97ffa5d4d..6699b00c0 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -201,7 +201,7 @@ void JavaPage::on_javaTestBtn_clicked() void JavaPage::on_downloadJavaButton_clicked() { - auto jdialog = new Java::InstallDialog({}, this); + auto jdialog = new Java::InstallDialog({}, nullptr, this); jdialog->exec(); ui->managedJavaList->loadList(); } diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 6e6b1db57..364f64e19 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -390,7 +390,7 @@ void InstanceSettingsPage::loadSettings() void InstanceSettingsPage::on_javaDownloadBtn_clicked() { - auto jdialog = new Java::InstallDialog({}, this); + auto jdialog = new Java::InstallDialog({}, m_instance, this); jdialog->exec(); } diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index ec1ed0605..fb90afe1d 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -351,7 +351,7 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked() void JavaSettingsWidget::javaDownloadBtn_clicked() { - auto jdialog = new Java::InstallDialog({}, this); + auto jdialog = new Java::InstallDialog({}, nullptr, this); jdialog->exec(); } From ba7391308e2b4e22c87d66468a1c837fa34b444b Mon Sep 17 00:00:00 2001 From: Edgars Cirulis Date: Mon, 5 Aug 2024 22:05:23 +0300 Subject: [PATCH 096/120] Restore connect line for device authorization in MSADeviceCodeStep Parent PRs: https://github.com/PrismLauncher/PrismLauncher/pull/2617 Fixes https://github.com/PrismLauncher/PrismLauncher/issues/2705 Signed-off-by: Edgars Cirulis --- launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp index 9626dfeb4..c283b153e 100644 --- a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp +++ b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp @@ -74,6 +74,8 @@ void MSADeviceCodeStep::perform() m_task->setAskRetry(false); m_task->addNetAction(m_request); + connect(m_task.get(), &Task::finished, this, &MSADeviceCodeStep::deviceAutorizationFinished); + m_task->start(); } From 128827cef50d7ab4e332e8e26bc21db425237de3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 20:02:40 +0000 Subject: [PATCH 097/120] chore(deps): update hendrikmuhs/ccache-action action to v1.2.14 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aa6e8f64f..a521a6e45 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -160,7 +160,7 @@ jobs: - name: Setup ccache if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug' - uses: hendrikmuhs/ccache-action@v1.2.13 + uses: hendrikmuhs/ccache-action@v1.2.14 with: key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }} From 659fa7fbfb3a5e761efbaeb207a9014b7affafde Mon Sep 17 00:00:00 2001 From: Kationor Date: Wed, 7 Aug 2024 16:21:34 +0200 Subject: [PATCH 098/120] fix/windows: Check registry for per-user java installations Signed-off-by: Kationor --- launcher/java/JavaUtils.cpp | 78 +++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 34d893ff2..350ccc30d 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -182,56 +182,58 @@ QList JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString else if (keyType == KEY_WOW64_32KEY) archType = "32"; - HKEY jreKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName.toStdWString().c_str(), 0, KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == - ERROR_SUCCESS) { - // Read the current type version from the registry. - // This will be used to find any key that contains the JavaHome value. + for (HKEY baseRegistry : { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }) { + HKEY jreKey; + if (RegOpenKeyExW(baseRegistry, keyName.toStdWString().c_str(), 0, KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == + ERROR_SUCCESS) { + // Read the current type version from the registry. + // This will be used to find any key that contains the JavaHome value. - WCHAR subKeyName[255]; - DWORD subKeyNameSize, numSubKeys, retCode; + WCHAR subKeyName[255]; + DWORD subKeyNameSize, numSubKeys, retCode; - // Get the number of subkeys - RegQueryInfoKeyW(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + // Get the number of subkeys + RegQueryInfoKeyW(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - // Iterate until RegEnumKeyEx fails - if (numSubKeys > 0) { - for (DWORD i = 0; i < numSubKeys; i++) { - subKeyNameSize = 255; - retCode = RegEnumKeyExW(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL); - QString newSubkeyName = QString::fromWCharArray(subKeyName); - if (retCode == ERROR_SUCCESS) { - // Now open the registry key for the version that we just got. - QString newKeyName = keyName + "\\" + newSubkeyName + subkeySuffix; + // Iterate until RegEnumKeyEx fails + if (numSubKeys > 0) { + for (DWORD i = 0; i < numSubKeys; i++) { + subKeyNameSize = 255; + retCode = RegEnumKeyExW(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL); + QString newSubkeyName = QString::fromWCharArray(subKeyName); + if (retCode == ERROR_SUCCESS) { + // Now open the registry key for the version that we just got. + QString newKeyName = keyName + "\\" + newSubkeyName + subkeySuffix; - HKEY newKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, newKeyName.toStdWString().c_str(), 0, KEY_READ | keyType, &newKey) == - ERROR_SUCCESS) { - // Read the JavaHome value to find where Java is installed. - DWORD valueSz = 0; - if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, NULL, &valueSz) == ERROR_SUCCESS) { - WCHAR* value = new WCHAR[valueSz]; - RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE*)value, &valueSz); + HKEY newKey; + if (RegOpenKeyExW(baseRegistry, newKeyName.toStdWString().c_str(), 0, KEY_READ | keyType, &newKey) == + ERROR_SUCCESS) { + // Read the JavaHome value to find where Java is installed. + DWORD valueSz = 0; + if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, NULL, &valueSz) == ERROR_SUCCESS) { + WCHAR* value = new WCHAR[valueSz]; + RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE*)value, &valueSz); - QString newValue = QString::fromWCharArray(value); - delete[] value; + QString newValue = QString::fromWCharArray(value); + delete[] value; - // Now, we construct the version object and add it to the list. - JavaInstallPtr javaVersion(new JavaInstall()); + // Now, we construct the version object and add it to the list. + JavaInstallPtr javaVersion(new JavaInstall()); - javaVersion->id = newSubkeyName; - javaVersion->arch = archType; - javaVersion->path = QDir(FS::PathCombine(newValue, "bin")).absoluteFilePath("javaw.exe"); - javas.append(javaVersion); + javaVersion->id = newSubkeyName; + javaVersion->arch = archType; + javaVersion->path = QDir(FS::PathCombine(newValue, "bin")).absoluteFilePath("javaw.exe"); + javas.append(javaVersion); + } + + RegCloseKey(newKey); } - - RegCloseKey(newKey); } } } - } - RegCloseKey(jreKey); + RegCloseKey(jreKey); + } } return javas; From c9809fff6d88643e723b492dde835bd806a9c076 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Aug 2024 16:53:26 +0300 Subject: [PATCH 099/120] add setting for quickplay singleplayer Signed-off-by: Trial97 --- launcher/Application.cpp | 47 +++++++------ launcher/Application.h | 7 +- launcher/BaseInstance.h | 6 +- launcher/CMakeLists.txt | 4 +- launcher/InstancePageProvider.h | 4 +- launcher/LaunchController.cpp | 2 +- launcher/LaunchController.h | 8 +-- launcher/NullInstance.h | 6 +- launcher/launch/steps/LookupServerAddress.cpp | 2 +- launcher/launch/steps/LookupServerAddress.h | 8 +-- launcher/minecraft/MinecraftInstance.cpp | 69 +++++++++++-------- launcher/minecraft/MinecraftInstance.h | 12 ++-- .../minecraft/launch/LauncherPartLaunch.cpp | 2 +- .../minecraft/launch/LauncherPartLaunch.h | 8 +-- ...ftServerTarget.cpp => MinecraftTarget.cpp} | 11 ++- ...ecraftServerTarget.h => MinecraftTarget.h} | 8 +-- .../minecraft/launch/PrintInstanceInfo.cpp | 2 +- launcher/minecraft/launch/PrintInstanceInfo.h | 11 ++- .../pages/instance/InstanceSettingsPage.cpp | 57 ++++++++++++++- .../ui/pages/instance/InstanceSettingsPage.h | 3 + .../ui/pages/instance/InstanceSettingsPage.ui | 42 +++++------ launcher/ui/pages/instance/ServersPage.cpp | 4 +- launcher/ui/pages/instance/WorldListPage.cpp | 18 ++++- launcher/ui/pages/instance/WorldListPage.h | 5 +- launcher/ui/pages/instance/WorldListPage.ui | 6 ++ launcher/ui/widgets/WideBar.cpp | 13 ++++ launcher/ui/widgets/WideBar.h | 2 + .../launcher/impl/AbstractLauncher.java | 3 +- .../launcher/impl/StandardLauncher.java | 11 ++- 29 files changed, 253 insertions(+), 128 deletions(-) rename launcher/minecraft/launch/{MinecraftServerTarget.cpp => MinecraftTarget.cpp} (86%) rename launcher/minecraft/launch/{MinecraftServerTarget.h => MinecraftTarget.h} (80%) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 6c0319984..84b759e09 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -236,6 +236,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) { { { "d", "dir" }, "Use a custom path as application root (use '.' for current directory)", "directory" }, { { "l", "launch" }, "Launch the specified instance (by instance ID)", "instance" }, { { "s", "server" }, "Join the specified server on launch (only valid in combination with --launch)", "address" }, + { { "w", "world" }, "Join the specified world on launch (only valid in combination with --launch)", "world" }, { { "a", "profile" }, "Use the account specified by its profile name (only valid in combination with --launch)", "profile" }, { "alive", "Write a small '" + liveCheckFile + "' file after the launcher starts" }, { { "I", "import" }, "Import instance or resource from specified local path or URL", "url" }, @@ -249,7 +250,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) parser.process(arguments()); m_instanceIdToLaunch = parser.value("launch"); - m_serverToJoin = parser.value("server"); + m_server_to_join = parser.value("server"); + m_world_to_join = parser.value("world"); m_profileToUse = parser.value("profile"); m_liveCheck = parser.isSet("alive"); @@ -265,7 +267,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) } // error if --launch is missing with --server or --profile - if ((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { + if (((!m_server_to_join.isEmpty() || !m_world_to_join.isEmpty()) || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl; m_status = Application::Failed; return; @@ -383,8 +385,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) launch.command = "launch"; launch.args["id"] = m_instanceIdToLaunch; - if (!m_serverToJoin.isEmpty()) { - launch.args["server"] = m_serverToJoin; + if (!m_server_to_join.isEmpty()) { + launch.args["server"] = m_server_to_join; + } else if (!m_world_to_join.isEmpty()) { + launch.args["world"] = m_world_to_join; } if (!m_profileToUse.isEmpty()) { launch.args["profile"] = m_profileToUse; @@ -521,8 +525,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) if (!m_instanceIdToLaunch.isEmpty()) { qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch; } - if (!m_serverToJoin.isEmpty()) { - qDebug() << "Address of server to join :" << m_serverToJoin; + if (!m_server_to_join.isEmpty()) { + qDebug() << "Address of server to join :" << m_server_to_join; + } else if (!m_world_to_join.isEmpty()) { + qDebug() << "Name of the world to join :" << m_world_to_join; } qDebug() << "<> Paths set."; } @@ -1157,14 +1163,17 @@ void Application::performMainStartupAction() if (!m_instanceIdToLaunch.isEmpty()) { auto inst = instances()->getInstanceById(m_instanceIdToLaunch); if (inst) { - MinecraftServerTargetPtr serverToJoin = nullptr; + MinecraftTarget::Ptr targetToJoin = nullptr; MinecraftAccountPtr accountToUse = nullptr; qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching"; - if (!m_serverToJoin.isEmpty()) { + if (!m_server_to_join.isEmpty()) { // FIXME: validate the server string - serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(m_serverToJoin))); - qDebug() << " Launching with server" << m_serverToJoin; + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_server_to_join, false))); + qDebug() << " Launching with server" << m_server_to_join; + } else if (!m_world_to_join.isEmpty()) { + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_world_to_join, true))); + qDebug() << " Launching with world" << m_world_to_join; } if (!m_profileToUse.isEmpty()) { @@ -1175,7 +1184,7 @@ void Application::performMainStartupAction() qDebug() << " Launching with account" << m_profileToUse; } - launch(inst, true, false, serverToJoin, accountToUse); + launch(inst, true, false, targetToJoin, accountToUse); return; } } @@ -1265,6 +1274,7 @@ void Application::messageReceived(const QByteArray& message) } else if (command == "launch") { QString id = received.args["id"]; QString server = received.args["server"]; + QString world = received.args["world"]; QString profile = received.args["profile"]; InstancePtr instance; @@ -1279,11 +1289,12 @@ void Application::messageReceived(const QByteArray& message) return; } - MinecraftServerTargetPtr serverObject = nullptr; + MinecraftTarget::Ptr serverObject = nullptr; if (!server.isEmpty()) { - serverObject = std::make_shared(MinecraftServerTarget::parse(server)); + serverObject = std::make_shared(MinecraftTarget::parse(server, false)); + } else if (!world.isEmpty()) { + serverObject = std::make_shared(MinecraftTarget::parse(world, true)); } - MinecraftAccountPtr accountObject; if (!profile.isEmpty()) { accountObject = accounts()->getAccountByProfileName(profile); @@ -1332,11 +1343,7 @@ bool Application::openJsonEditor(const QString& filename) } } -bool Application::launch(InstancePtr instance, - bool online, - bool demo, - MinecraftServerTargetPtr serverToJoin, - MinecraftAccountPtr accountToUse) +bool Application::launch(InstancePtr instance, bool online, bool demo, MinecraftTarget::Ptr targetToJoin, MinecraftAccountPtr accountToUse) { if (m_updateRunning) { qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed."; @@ -1354,7 +1361,7 @@ bool Application::launch(InstancePtr instance, controller->setOnline(online); controller->setDemo(demo); controller->setProfiler(profilers().value(instance->settings()->get("Profiler").toString(), nullptr).get()); - controller->setServerToJoin(serverToJoin); + controller->setTargetToJoin(targetToJoin); controller->setAccountToUse(accountToUse); if (window) { controller->setParentWidget(window); diff --git a/launcher/Application.h b/launcher/Application.h index 8303c7475..fb54b1005 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -47,7 +47,7 @@ #include -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" class LaunchController; class LocalPeer; @@ -202,7 +202,7 @@ class Application : public QApplication { bool launch(InstancePtr instance, bool online = true, bool demo = false, - MinecraftServerTargetPtr serverToJoin = nullptr, + MinecraftTarget::Ptr targetToJoin = nullptr, MinecraftAccountPtr accountToUse = nullptr); bool kill(InstancePtr instance); void closeCurrentWindow(); @@ -289,7 +289,8 @@ class Application : public QApplication { QString m_detectedGLFWPath; QString m_detectedOpenALPath; QString m_instanceIdToLaunch; - QString m_serverToJoin; + QString m_server_to_join; + QString m_world_to_join; QString m_profileToUse; bool m_liveCheck = false; QList m_urlsToImport; diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h index 499ec7866..8c80331bc 100644 --- a/launcher/BaseInstance.h +++ b/launcher/BaseInstance.h @@ -56,7 +56,7 @@ #include "net/Mode.h" #include "RuntimeContext.h" -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" class QDir; class Task; @@ -184,7 +184,7 @@ class BaseInstance : public QObject, public std::enable_shared_from_this createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0; + virtual shared_qobject_ptr createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) = 0; /// returns the current launch task (if any) shared_qobject_ptr getLaunchTask(); @@ -256,7 +256,7 @@ class BaseInstance : public QObject, public std::enable_shared_from_this getPages() override { QList values; @@ -39,7 +39,7 @@ class InstancePageProvider : protected QObject, public BasePageProvider { values.append(new TexturePackPage(onesix.get(), onesix->texturePackList())); values.append(new ShaderPackPage(onesix.get(), onesix->shaderPackList())); values.append(new NotesPage(onesix.get())); - values.append(new WorldListPage(onesix.get(), onesix->worldList())); + values.append(new WorldListPage(onesix, onesix->worldList())); values.append(new ServersPage(onesix)); // values.append(new GameOptionsPage(onesix.get())); values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 3866a7672..83bf3838e 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -324,7 +324,7 @@ void LaunchController::launchInstance() return; } - m_launcher = m_instance->createLaunchTask(m_session, m_serverToJoin); + m_launcher = m_instance->createLaunchTask(m_session, m_target_to_join); if (!m_launcher) { emitFailed(tr("Couldn't instantiate a launcher.")); return; diff --git a/launcher/LaunchController.h b/launcher/LaunchController.h index bc688f2ba..e620b8c62 100644 --- a/launcher/LaunchController.h +++ b/launcher/LaunchController.h @@ -39,7 +39,7 @@ #include #include "minecraft/auth/MinecraftAccount.h" -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" class InstanceWindow; class LaunchController : public Task { @@ -48,7 +48,7 @@ class LaunchController : public Task { void executeTask() override; LaunchController(QObject* parent = nullptr); - virtual ~LaunchController() {}; + virtual ~LaunchController() = default; void setInstance(InstancePtr instance) { m_instance = instance; } @@ -62,7 +62,7 @@ class LaunchController : public Task { void setParentWidget(QWidget* widget) { m_parentWidget = widget; } - void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { m_serverToJoin = std::move(serverToJoin); } + void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_target_to_join = std::move(targetToJoin); } void setAccountToUse(MinecraftAccountPtr accountToUse) { m_accountToUse = std::move(accountToUse); } @@ -94,5 +94,5 @@ class LaunchController : public Task { MinecraftAccountPtr m_accountToUse = nullptr; AuthSessionPtr m_session; shared_qobject_ptr m_launcher; - MinecraftServerTargetPtr m_serverToJoin; + MinecraftTarget::Ptr m_target_to_join; }; diff --git a/launcher/NullInstance.h b/launcher/NullInstance.h index b6a9478a8..3ee38e76c 100644 --- a/launcher/NullInstance.h +++ b/launcher/NullInstance.h @@ -46,13 +46,13 @@ class NullInstance : public BaseInstance { { setVersionBroken(true); } - virtual ~NullInstance() {}; + virtual ~NullInstance() = default; void saveNow() override {} void loadSpecificSettings() override { setSpecificSettingsLoaded(true); } QString getStatusbarDescription() override { return tr("Unknown instance type"); }; QSet traits() const override { return {}; }; QString instanceConfigFolder() const override { return instanceRoot(); }; - shared_qobject_ptr createLaunchTask(AuthSessionPtr, MinecraftServerTargetPtr) override { return nullptr; } + shared_qobject_ptr createLaunchTask(AuthSessionPtr, MinecraftTarget::Ptr) override { return nullptr; } shared_qobject_ptr createUpdateTask([[maybe_unused]] Net::Mode mode) override { return nullptr; } QProcessEnvironment createEnvironment() override { return QProcessEnvironment(); } QProcessEnvironment createLaunchEnvironment() override { return QProcessEnvironment(); } @@ -64,7 +64,7 @@ class NullInstance : public BaseInstance { bool canEdit() const override { return false; } bool canLaunch() const override { return false; } void populateLaunchMenu(QMenu* menu) override {} - QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override + QStringList verboseDescription(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) override { QStringList out; out << "Null instance - placeholder."; diff --git a/launcher/launch/steps/LookupServerAddress.cpp b/launcher/launch/steps/LookupServerAddress.cpp index 9bdac203b..4b67b3092 100644 --- a/launcher/launch/steps/LookupServerAddress.cpp +++ b/launcher/launch/steps/LookupServerAddress.cpp @@ -30,7 +30,7 @@ void LookupServerAddress::setLookupAddress(const QString& lookupAddress) m_dnsLookup->setName(QString("_minecraft._tcp.%1").arg(lookupAddress)); } -void LookupServerAddress::setOutputAddressPtr(MinecraftServerTargetPtr output) +void LookupServerAddress::setOutputAddressPtr(MinecraftTarget::Ptr output) { m_output = std::move(output); } diff --git a/launcher/launch/steps/LookupServerAddress.h b/launcher/launch/steps/LookupServerAddress.h index acbd74309..506314ee8 100644 --- a/launcher/launch/steps/LookupServerAddress.h +++ b/launcher/launch/steps/LookupServerAddress.h @@ -19,20 +19,20 @@ #include #include -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" class LookupServerAddress : public LaunchStep { Q_OBJECT public: explicit LookupServerAddress(LaunchTask* parent); - virtual ~LookupServerAddress() {}; + virtual ~LookupServerAddress() = default; virtual void executeTask(); virtual bool abort(); virtual bool canAbort() const { return true; } void setLookupAddress(const QString& lookupAddress); - void setOutputAddressPtr(MinecraftServerTargetPtr output); + void setOutputAddressPtr(MinecraftTarget::Ptr output); private slots: void on_dnsLookupFinished(); @@ -42,5 +42,5 @@ class LookupServerAddress : public LaunchStep { QDnsLookup* m_dnsLookup; QString m_lookupAddress; - MinecraftServerTargetPtr m_output; + MinecraftTarget::Ptr m_output; }; diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index d119104fe..c50d57513 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -196,8 +196,9 @@ void MinecraftInstance::loadSpecificSettings() } // Join server on launch, this does not have a global override - m_settings->registerSetting("JoinServerOnLaunch", false); + m_settings->registerSetting({ "JoinServerOnLaunch", "JoinOnLaunch" }, false); m_settings->registerSetting("JoinServerOnLaunchAddress", ""); + m_settings->registerSetting("JoinWorldOnLaunch", ""); // Use account for instance, this does not have a global override m_settings->registerSetting("UseAccountForInstance", false); @@ -523,8 +524,7 @@ QStringList MinecraftInstance::javaArguments() if (javaVersion.isModular() && shouldApplyOnlineFixes()) // allow reflective access to java.net - required by the skin fix - args << "--add-opens" - << "java.base/java.net=ALL-UNNAMED"; + args << "--add-opens" << "java.base/java.net=ALL-UNNAMED"; return args; } @@ -656,7 +656,7 @@ static QString replaceTokensIn(QString text, QMap with) return result; } -QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) const +QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) const { auto profile = m_components->getProfile(); QString args_pattern = profile->getMinecraftArguments(); @@ -664,12 +664,16 @@ QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, Mine args_pattern += " --tweakClass " + tweaker; } - if (serverToJoin && !serverToJoin->address.isEmpty()) { - if (profile->hasTrait("feature:is_quick_play_multiplayer")) { - args_pattern += " --quickPlayMultiplayer " + serverToJoin->address + ':' + QString::number(serverToJoin->port); - } else { - args_pattern += " --server " + serverToJoin->address; - args_pattern += " --port " + QString::number(serverToJoin->port); + if (targetToJoin) { + if (!targetToJoin->address.isEmpty()) { + if (profile->hasTrait("feature:is_quick_play_multiplayer")) { + args_pattern += " --quickPlayMultiplayer " + targetToJoin->address + ':' + QString::number(targetToJoin->port); + } else { + args_pattern += " --server " + targetToJoin->address; + args_pattern += " --port " + QString::number(targetToJoin->port); + } + } else if (!targetToJoin->world.isEmpty() && profile->hasTrait("feature:is_quick_play_singleplayer")) { + args_pattern += " --quickPlaySingleplayer " + targetToJoin->world; } } @@ -713,7 +717,7 @@ QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, Mine return parts; } -QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) +QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) { QString launchScript; @@ -732,9 +736,13 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS launchScript += "appletClass " + appletClass + "\n"; } - if (serverToJoin && !serverToJoin->address.isEmpty()) { - launchScript += "serverAddress " + serverToJoin->address + "\n"; - launchScript += "serverPort " + QString::number(serverToJoin->port) + "\n"; + if (targetToJoin) { + if (!targetToJoin->address.isEmpty()) { + launchScript += "serverAddress " + targetToJoin->address + "\n"; + launchScript += "serverPort " + QString::number(targetToJoin->port) + "\n"; + } else if (!targetToJoin->world.isEmpty()) { + launchScript += "worldName " + targetToJoin->world + "\n"; + } } // generic minecraft params @@ -787,13 +795,11 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS return launchScript; } -QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) +QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) { QStringList out; - out << "Main Class:" - << " " + getMainClass() << ""; - out << "Native path:" - << " " + getNativePath() << ""; + out << "Main Class:" << " " + getMainClass() << ""; + out << "Native path:" << " " + getNativePath() << ""; auto profile = m_components->getProfile(); @@ -884,7 +890,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << ""; } - auto params = processMinecraftArgs(nullptr, serverToJoin); + auto params = processMinecraftArgs(nullptr, targetToJoin); out << "Params:"; out << " " + params.join(' '); out << ""; @@ -1034,7 +1040,7 @@ Task::Ptr MinecraftInstance::createUpdateTask(Net::Mode mode) return nullptr; } -shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) +shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) { updateRuntimeContext(); // FIXME: get rid of shared_from_this ... @@ -1058,16 +1064,23 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(makeShared(pptr)); } - if (!serverToJoin && settings()->get("JoinServerOnLaunch").toBool()) { + if (!targetToJoin && settings()->get("JoinOnLaunch").toBool()) { QString fullAddress = settings()->get("JoinServerOnLaunchAddress").toString(); - serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(fullAddress))); + if (!fullAddress.isEmpty()) { + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(fullAddress, false))); + } else { + QString world = settings()->get("JoinWorldOnLaunch").toString(); + if (!world.isEmpty()) { + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(world, true))); + } + } } - if (serverToJoin && serverToJoin->port == 25565) { + if (targetToJoin && targetToJoin->port == 25565) { // Resolve server address to join on launch auto step = makeShared(pptr); - step->setLookupAddress(serverToJoin->address); - step->setOutputAddressPtr(serverToJoin); + step->setLookupAddress(targetToJoin->address); + step->setOutputAddressPtr(targetToJoin); process->appendStep(step); } @@ -1100,7 +1113,7 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt // print some instance info here... { - process->appendStep(makeShared(pptr, session, serverToJoin)); + process->appendStep(makeShared(pptr, session, targetToJoin)); } // extract native jars if needed @@ -1123,7 +1136,7 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt auto step = makeShared(pptr); step->setWorkingDirectory(gameRoot()); step->setAuthSession(session); - step->setServerToJoin(serverToJoin); + step->setTargetToJoin(targetToJoin); process->appendStep(step); } diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 7af0df389..ad2cda186 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -39,7 +39,7 @@ #include #include #include "BaseInstance.h" -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" #include "minecraft/mod/Mod.h" class ModFolderModel; @@ -56,7 +56,7 @@ class MinecraftInstance : public BaseInstance { Q_OBJECT public: MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir); - virtual ~MinecraftInstance() {}; + virtual ~MinecraftInstance() = default; virtual void saveNow() override; void loadSpecificSettings() override; @@ -121,11 +121,11 @@ class MinecraftInstance : public BaseInstance { ////// Launch stuff ////// Task::Ptr createUpdateTask(Net::Mode mode) override; - shared_qobject_ptr createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override; + shared_qobject_ptr createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) override; QStringList extraArguments() override; - QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override; + QStringList verboseDescription(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) override; QList getJarMods() const; - QString createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin); + QString createLaunchScript(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin); /// get arguments passed to java QStringList javaArguments(); QString getLauncher(); @@ -155,7 +155,7 @@ class MinecraftInstance : public BaseInstance { virtual QString getMainClass() const; // FIXME: remove - virtual QStringList processMinecraftArgs(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) const; + virtual QStringList processMinecraftArgs(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) const; virtual JavaVersion getJavaVersion(); diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index b35d55924..be1bde464 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -90,7 +90,7 @@ void LauncherPartLaunch::executeTask() } } - m_launchScript = minecraftInstance->createLaunchScript(m_session, m_serverToJoin); + m_launchScript = minecraftInstance->createLaunchScript(m_session, m_target_to_join); QStringList args = minecraftInstance->javaArguments(); QString allArgs = args.join(", "); emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::Launcher); diff --git a/launcher/minecraft/launch/LauncherPartLaunch.h b/launcher/minecraft/launch/LauncherPartLaunch.h index fcd4daec6..ca0906550 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.h +++ b/launcher/minecraft/launch/LauncherPartLaunch.h @@ -19,13 +19,13 @@ #include #include -#include "MinecraftServerTarget.h" +#include "MinecraftTarget.h" class LauncherPartLaunch : public LaunchStep { Q_OBJECT public: explicit LauncherPartLaunch(LaunchTask* parent); - virtual ~LauncherPartLaunch() {}; + virtual ~LauncherPartLaunch() = default; virtual void executeTask(); virtual bool abort(); @@ -34,7 +34,7 @@ class LauncherPartLaunch : public LaunchStep { void setWorkingDirectory(const QString& wd); void setAuthSession(AuthSessionPtr session) { m_session = session; } - void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { m_serverToJoin = std::move(serverToJoin); } + void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_target_to_join = std::move(targetToJoin); } private slots: void on_state(LoggedProcess::State state); @@ -44,7 +44,7 @@ class LauncherPartLaunch : public LaunchStep { QString m_command; AuthSessionPtr m_session; QString m_launchScript; - MinecraftServerTargetPtr m_serverToJoin; + MinecraftTarget::Ptr m_target_to_join; bool mayProceed = false; }; diff --git a/launcher/minecraft/launch/MinecraftServerTarget.cpp b/launcher/minecraft/launch/MinecraftTarget.cpp similarity index 86% rename from launcher/minecraft/launch/MinecraftServerTarget.cpp rename to launcher/minecraft/launch/MinecraftTarget.cpp index e201efab1..ba9f87511 100644 --- a/launcher/minecraft/launch/MinecraftServerTarget.cpp +++ b/launcher/minecraft/launch/MinecraftTarget.cpp @@ -13,13 +13,18 @@ * limitations under the License. */ -#include "MinecraftServerTarget.h" +#include "MinecraftTarget.h" #include // FIXME: the way this is written, it can't ever do any sort of validation and can accept total junk -MinecraftServerTarget MinecraftServerTarget::parse(const QString& fullAddress) +MinecraftTarget MinecraftTarget::parse(const QString& fullAddress, bool useWorld) { + if (useWorld) { + MinecraftTarget target; + target.world = fullAddress; + return target; + } QStringList split = fullAddress.split(":"); // The logic below replicates the exact logic minecraft uses for parsing server addresses. @@ -56,5 +61,5 @@ MinecraftServerTarget MinecraftServerTarget::parse(const QString& fullAddress) } } - return MinecraftServerTarget{ realAddress, realPort }; + return MinecraftTarget{ realAddress, realPort }; } diff --git a/launcher/minecraft/launch/MinecraftServerTarget.h b/launcher/minecraft/launch/MinecraftTarget.h similarity index 80% rename from launcher/minecraft/launch/MinecraftServerTarget.h rename to launcher/minecraft/launch/MinecraftTarget.h index 2edd8a30d..7f8b268d9 100644 --- a/launcher/minecraft/launch/MinecraftServerTarget.h +++ b/launcher/minecraft/launch/MinecraftTarget.h @@ -19,11 +19,11 @@ #include -struct MinecraftServerTarget { +struct MinecraftTarget { QString address; quint16 port; - static MinecraftServerTarget parse(const QString& fullAddress); + QString world; + static MinecraftTarget parse(const QString& fullAddress, bool useWorld); + using Ptr = std::shared_ptr; }; - -using MinecraftServerTargetPtr = std::shared_ptr; diff --git a/launcher/minecraft/launch/PrintInstanceInfo.cpp b/launcher/minecraft/launch/PrintInstanceInfo.cpp index e3a45b030..78cb26378 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.cpp +++ b/launcher/minecraft/launch/PrintInstanceInfo.cpp @@ -129,6 +129,6 @@ void PrintInstanceInfo::executeTask() #endif logLines(log, MessageLevel::Launcher); - logLines(instance->verboseDescription(m_session, m_serverToJoin), MessageLevel::Launcher); + logLines(instance->verboseDescription(m_session, m_target_to_join), MessageLevel::Launcher); emitSucceeded(); } diff --git a/launcher/minecraft/launch/PrintInstanceInfo.h b/launcher/minecraft/launch/PrintInstanceInfo.h index 93c5f0fd6..780ac5b2c 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.h +++ b/launcher/minecraft/launch/PrintInstanceInfo.h @@ -16,22 +16,21 @@ #pragma once #include -#include #include "minecraft/auth/AuthSession.h" -#include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/launch/MinecraftTarget.h" // FIXME: temporary wrapper for existing task. class PrintInstanceInfo : public LaunchStep { Q_OBJECT public: - explicit PrintInstanceInfo(LaunchTask* parent, AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) - : LaunchStep(parent), m_session(session), m_serverToJoin(serverToJoin) {}; - virtual ~PrintInstanceInfo() {}; + explicit PrintInstanceInfo(LaunchTask* parent, AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) + : LaunchStep(parent), m_session(session), m_target_to_join(targetToJoin) {}; + virtual ~PrintInstanceInfo() = default; virtual void executeTask(); virtual bool canAbort() const { return false; } private: AuthSessionPtr m_session; - MinecraftServerTargetPtr m_serverToJoin; + MinecraftTarget::Ptr m_target_to_join; }; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 76add9402..a017d5e13 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -36,6 +36,8 @@ */ #include "InstanceSettingsPage.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/WorldList.h" #include "ui_InstanceSettingsPage.h" #include @@ -71,6 +73,22 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance* inst, QWidget* parent) connect(ui->useNativeGLFWCheck, &QAbstractButton::toggled, this, &InstanceSettingsPage::onUseNativeGLFWChanged); connect(ui->useNativeOpenALCheck, &QAbstractButton::toggled, this, &InstanceSettingsPage::onUseNativeOpenALChanged); + auto mInst = dynamic_cast(inst); + m_world_quickplay_supported = mInst && mInst->traits().contains("feature:is_quick_play_singleplayer"); + if (m_world_quickplay_supported) { + auto worlds = mInst->worldList(); + worlds->update(); + for (const auto& world : worlds->allWorlds()) { + ui->worldsCb->addItem(world.folderName()); + } + } else { + ui->worldsCb->hide(); + ui->worldJoinButton->hide(); + ui->serverJoinAddressButton->setChecked(true); + ui->serverJoinAddress->setEnabled(true); + ui->serverJoinAddressButton->setStyleSheet("QRadioButton::indicator { width: 0px; height: 0px; }"); + } + loadSettings(); updateThresholds(); @@ -256,9 +274,16 @@ void InstanceSettingsPage::applySettings() bool joinServerOnLaunch = ui->serverJoinGroupBox->isChecked(); m_settings->set("JoinServerOnLaunch", joinServerOnLaunch); if (joinServerOnLaunch) { - m_settings->set("JoinServerOnLaunchAddress", ui->serverJoinAddress->text()); + if (ui->serverJoinAddressButton->isChecked() || !m_world_quickplay_supported) { + m_settings->set("JoinServerOnLaunchAddress", ui->serverJoinAddress->text()); + m_settings->reset("JoinWorldOnLaunch"); + } else { + m_settings->set("JoinWorldOnLaunch", ui->worldsCb->currentText()); + m_settings->reset("JoinServerOnLaunchAddress"); + } } else { m_settings->reset("JoinServerOnLaunchAddress"); + m_settings->reset("JoinWorldOnLaunch"); } // Use an account for this instance @@ -379,7 +404,25 @@ void InstanceSettingsPage::loadSettings() ui->recordGameTime->setChecked(m_settings->get("RecordGameTime").toBool()); ui->serverJoinGroupBox->setChecked(m_settings->get("JoinServerOnLaunch").toBool()); - ui->serverJoinAddress->setText(m_settings->get("JoinServerOnLaunchAddress").toString()); + + if (auto server = m_settings->get("JoinServerOnLaunchAddress").toString(); !server.isEmpty()) { + ui->serverJoinAddress->setText(server); + ui->serverJoinAddressButton->setChecked(true); + ui->worldJoinButton->setChecked(false); + ui->serverJoinAddress->setEnabled(true); + ui->worldsCb->setEnabled(false); + } else if (auto world = m_settings->get("JoinWorldOnLaunch").toString(); !world.isEmpty() && m_world_quickplay_supported) { + ui->worldsCb->setCurrentText(world); + ui->serverJoinAddressButton->setChecked(false); + ui->worldJoinButton->setChecked(true); + ui->serverJoinAddress->setEnabled(false); + ui->worldsCb->setEnabled(true); + } else { + ui->serverJoinAddressButton->setChecked(true); + ui->worldJoinButton->setChecked(false); + ui->serverJoinAddress->setEnabled(true); + ui->worldsCb->setEnabled(false); + } ui->instanceAccountGroupBox->setChecked(m_settings->get("UseAccountForInstance").toBool()); updateAccountsMenu(); @@ -534,3 +577,13 @@ void InstanceSettingsPage::updateThresholds() ui->labelMaxMemIcon->setPixmap(pix); } } + +void InstanceSettingsPage::on_serverJoinAddressButton_toggled(bool checked) +{ + ui->serverJoinAddress->setEnabled(checked); +} + +void InstanceSettingsPage::on_worldJoinButton_toggled(bool checked) +{ + ui->worldsCb->setEnabled(checked); +} diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 8b78dcb7f..6364502c9 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -70,6 +70,8 @@ class InstanceSettingsPage : public QWidget, public BasePage { void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); void on_maxMemSpinBox_valueChanged(int i); + void on_serverJoinAddressButton_toggled(bool checked); + void on_worldJoinButton_toggled(bool checked); void onUseNativeGLFWChanged(bool checked); void onUseNativeOpenALChanged(bool checked); @@ -90,4 +92,5 @@ class InstanceSettingsPage : public QWidget, public BasePage { BaseInstance* m_instance; SettingsObjectPtr m_settings; unique_qobject_ptr checker; + bool m_world_quickplay_supported; }; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 9490860ae..2f496318d 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -660,7 +660,7 @@ - Set a server to join on launch + Set a target to join on launch true @@ -668,26 +668,26 @@ false - - - - - - - - 0 - 0 - - - - Server address: - - - - - - - + + + + + Server address: + + + + + + + + + + Singleplayer world + + + + + diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index f842b4b93..d8035e73e 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -168,7 +168,7 @@ class ServersModel : public QAbstractListModel { m_saveTimer.setInterval(5000); connect(&m_saveTimer, &QTimer::timeout, this, &ServersModel::save_internal); } - virtual ~ServersModel() {}; + virtual ~ServersModel() = default; void observe() { @@ -731,7 +731,7 @@ void ServersPage::on_actionMove_Down_triggered() void ServersPage::on_actionJoin_triggered() { const auto& address = m_model->at(currentServer)->m_address; - APPLICATION->launch(m_inst, true, false, std::make_shared(MinecraftServerTarget::parse(address))); + APPLICATION->launch(m_inst, true, false, std::make_shared(MinecraftTarget::parse(address, false))); } #include "ServersPage.moc" diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index 4f30e4bb7..548d1025e 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -82,7 +82,7 @@ class WorldListProxyModel : public QSortFilterProxyModel { } }; -WorldListPage::WorldListPage(BaseInstance* inst, std::shared_ptr worlds, QWidget* parent) +WorldListPage::WorldListPage(InstancePtr inst, std::shared_ptr worlds, QWidget* parent) : QMainWindow(parent), m_inst(inst), ui(new Ui::WorldListPage), m_worlds(worlds) { ui->setupUi(this); @@ -120,6 +120,8 @@ void WorldListPage::openedImpl() m_wide_bar_setting = APPLICATION->settings()->getSetting(setting_name); ui->toolBar->setVisibilityState(m_wide_bar_setting->get().toByteArray()); + auto mInst = std::dynamic_pointer_cast(m_inst); + ui->toolBar->setActionVisible(ui->actionJoin, mInst && mInst->traits().contains("feature:is_quick_play_singleplayer")); } void WorldListPage::closedImpl() @@ -339,6 +341,9 @@ void WorldListPage::worldChanged([[maybe_unused]] const QModelIndex& current, [[ ui->actionDatapacks->setEnabled(enable); bool hasIcon = !index.data(WorldList::IconFileRole).isNull(); ui->actionReset_Icon->setEnabled(enable && hasIcon); + auto mInst = std::dynamic_pointer_cast(m_inst); + ui->actionJoin->setEnabled(enable); + ui->toolBar->setActionVisible(ui->actionJoin, mInst && mInst->traits().contains("feature:is_quick_play_singleplayer")); } void WorldListPage::on_actionAdd_triggered() @@ -418,4 +423,15 @@ void WorldListPage::on_actionRefresh_triggered() m_worlds->update(); } +void WorldListPage::on_actionJoin_triggered() +{ + QModelIndex index = getSelectedWorld(); + if (!index.isValid()) { + return; + } + auto worldVariant = m_worlds->data(index, WorldList::ObjectRole); + auto world = (World*)worldVariant.value(); + APPLICATION->launch(m_inst, true, false, std::make_shared(MinecraftTarget::parse(world->folderName(), true))); +} + #include "WorldListPage.moc" diff --git a/launcher/ui/pages/instance/WorldListPage.h b/launcher/ui/pages/instance/WorldListPage.h index 4f83002f4..84d9cd075 100644 --- a/launcher/ui/pages/instance/WorldListPage.h +++ b/launcher/ui/pages/instance/WorldListPage.h @@ -53,7 +53,7 @@ class WorldListPage : public QMainWindow, public BasePage { Q_OBJECT public: - explicit WorldListPage(BaseInstance* inst, std::shared_ptr worlds, QWidget* parent = 0); + explicit WorldListPage(InstancePtr inst, std::shared_ptr worlds, QWidget* parent = 0); virtual ~WorldListPage(); virtual QString displayName() const override { return tr("Worlds"); } @@ -72,7 +72,7 @@ class WorldListPage : public QMainWindow, public BasePage { QMenu* createPopupMenu() override; protected: - BaseInstance* m_inst; + InstancePtr m_inst; private: QModelIndex getSelectedWorld(); @@ -101,6 +101,7 @@ class WorldListPage : public QMainWindow, public BasePage { void on_actionReset_Icon_triggered(); void worldChanged(const QModelIndex& current, const QModelIndex& previous); void mceditState(LoggedProcess::State state); + void on_actionJoin_triggered(); void ShowContextMenu(const QPoint& pos); }; diff --git a/launcher/ui/pages/instance/WorldListPage.ui b/launcher/ui/pages/instance/WorldListPage.ui index d74dd0796..04344b453 100644 --- a/launcher/ui/pages/instance/WorldListPage.ui +++ b/launcher/ui/pages/instance/WorldListPage.ui @@ -81,6 +81,7 @@ + @@ -97,6 +98,11 @@ Add + + + Join + + Rename diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index 46caaaef2..455b14f69 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -309,4 +309,17 @@ bool WideBar::checkHash(QByteArray const& old_hash) const return old_hash == getHash(); } +void WideBar::setActionVisible(QAction* action, bool visible) +{ + auto iter = getMatching(action); + if (iter == m_entries.end()) { + return; + } + + iter->bar_action->setVisible(visible); + + // NOTE: This is needed so that disabled actions get reflected on the button when it is made visible. + static_cast(widgetForAction(iter->bar_action))->actionChanged(); +} + #include "WideBar.moc" diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index c47f3a596..09480594a 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -38,6 +38,8 @@ class WideBar : public QToolBar { [[nodiscard]] QByteArray getVisibilityState() const; void setVisibilityState(QByteArray&&); + void setActionVisible(QAction* action, bool visible); + private: struct BarEntry { enum class Type { None, Action, Separator, Spacer } type = Type::None; diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java b/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java index de28a0401..a5f027ba6 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java +++ b/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java @@ -70,7 +70,7 @@ public abstract class AbstractLauncher implements Launcher { // secondary parameters protected final int width, height; protected final boolean maximize; - protected final String serverAddress, serverPort; + protected final String serverAddress, serverPort, worldName; protected final String mainClassName; @@ -80,6 +80,7 @@ public abstract class AbstractLauncher implements Launcher { serverAddress = params.getString("serverAddress", null); serverPort = params.getString("serverPort", null); + worldName = params.getString("worldName", null); String windowParams = params.getString("windowParams", null); diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java b/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java index 49e5d518f..dc518be64 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java +++ b/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java @@ -62,13 +62,15 @@ import java.util.Collections; import java.util.List; public final class StandardLauncher extends AbstractLauncher { - private final boolean quickPlaySupported; + private final boolean quickPlayMultiplayerSupported; + private final boolean quickPlaySingleplayerSupported; public StandardLauncher(Parameters params) { super(params); List traits = params.getList("traits", Collections.emptyList()); - quickPlaySupported = traits.contains("feature:is_quick_play_multiplayer"); + quickPlayMultiplayerSupported = traits.contains("feature:is_quick_play_multiplayer"); + quickPlaySingleplayerSupported = traits.contains("feature:is_quick_play_singleplayer"); } @Override @@ -83,7 +85,7 @@ public final class StandardLauncher extends AbstractLauncher { } if (serverAddress != null) { - if (quickPlaySupported) { + if (quickPlayMultiplayerSupported) { // as of 23w14a gameArgs.add("--quickPlayMultiplayer"); gameArgs.add(serverAddress + ':' + serverPort); @@ -93,6 +95,9 @@ public final class StandardLauncher extends AbstractLauncher { gameArgs.add("--port"); gameArgs.add(serverPort); } + } else if (worldName != null && quickPlaySingleplayerSupported) { + gameArgs.add("--quickPlaySingleplayer"); + gameArgs.add(worldName); } // find and invoke the main method From a9c7e95c6652bc965fc1a4e8097cd4be22a3df23 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Aug 2024 19:39:32 +0300 Subject: [PATCH 100/120] fix widebar action removal Signed-off-by: Trial97 --- launcher/ui/pages/instance/WorldListPage.cpp | 16 ++++++++++++---- launcher/ui/widgets/WideBar.cpp | 12 +++++------- launcher/ui/widgets/WideBar.h | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index 548d1025e..4ed5f1f73 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -113,6 +113,11 @@ void WorldListPage::openedImpl() { m_worlds->startWatching(); + auto mInst = std::dynamic_pointer_cast(m_inst); + if (!mInst || !mInst->traits().contains("feature:is_quick_play_singleplayer")) { + ui->toolBar->removeAction(ui->actionJoin); + } + auto const setting_name = QString("WideBarVisibility_%1").arg(id()); if (!APPLICATION->settings()->contains(setting_name)) m_wide_bar_setting = APPLICATION->settings()->registerSetting(setting_name); @@ -120,8 +125,6 @@ void WorldListPage::openedImpl() m_wide_bar_setting = APPLICATION->settings()->getSetting(setting_name); ui->toolBar->setVisibilityState(m_wide_bar_setting->get().toByteArray()); - auto mInst = std::dynamic_pointer_cast(m_inst); - ui->toolBar->setActionVisible(ui->actionJoin, mInst && mInst->traits().contains("feature:is_quick_play_singleplayer")); } void WorldListPage::closedImpl() @@ -341,9 +344,14 @@ void WorldListPage::worldChanged([[maybe_unused]] const QModelIndex& current, [[ ui->actionDatapacks->setEnabled(enable); bool hasIcon = !index.data(WorldList::IconFileRole).isNull(); ui->actionReset_Icon->setEnabled(enable && hasIcon); + auto mInst = std::dynamic_pointer_cast(m_inst); - ui->actionJoin->setEnabled(enable); - ui->toolBar->setActionVisible(ui->actionJoin, mInst && mInst->traits().contains("feature:is_quick_play_singleplayer")); + auto supportsJoin = mInst && mInst->traits().contains("feature:is_quick_play_singleplayer"); + ui->actionJoin->setEnabled(enable && supportsJoin); + + if (!supportsJoin) { + ui->toolBar->removeAction(ui->actionJoin); + } } void WorldListPage::on_actionAdd_triggered() diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index 455b14f69..2940d7ce7 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -309,17 +309,15 @@ bool WideBar::checkHash(QByteArray const& old_hash) const return old_hash == getHash(); } -void WideBar::setActionVisible(QAction* action, bool visible) +void WideBar::removeAction(QAction* action) { auto iter = getMatching(action); - if (iter == m_entries.end()) { + if (iter == m_entries.end()) return; - } - iter->bar_action->setVisible(visible); - - // NOTE: This is needed so that disabled actions get reflected on the button when it is made visible. - static_cast(widgetForAction(iter->bar_action))->actionChanged(); + iter->bar_action->setVisible(false); + removeAction(iter->bar_action); + m_entries.erase(iter); } #include "WideBar.moc" diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index 09480594a..f4877a89a 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -38,7 +38,7 @@ class WideBar : public QToolBar { [[nodiscard]] QByteArray getVisibilityState() const; void setVisibilityState(QByteArray&&); - void setActionVisible(QAction* action, bool visible); + void removeAction(QAction* action); private: struct BarEntry { From dcca175b364498494623cbe436ab4b926e12bd34 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 9 Aug 2024 11:06:31 +0300 Subject: [PATCH 101/120] snake_case to m_camelCase Signed-off-by: Trial97 --- launcher/Application.cpp | 34 +++++++++---------- launcher/Application.h | 4 +-- launcher/LaunchController.cpp | 2 +- launcher/LaunchController.h | 4 +-- launcher/minecraft/MinecraftInstance.cpp | 6 ++++ .../minecraft/launch/LauncherPartLaunch.cpp | 2 +- .../minecraft/launch/LauncherPartLaunch.h | 4 +-- .../minecraft/launch/PrintInstanceInfo.cpp | 2 +- launcher/minecraft/launch/PrintInstanceInfo.h | 4 +-- 9 files changed, 34 insertions(+), 28 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 84b759e09..2137ed091 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -250,8 +250,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) parser.process(arguments()); m_instanceIdToLaunch = parser.value("launch"); - m_server_to_join = parser.value("server"); - m_world_to_join = parser.value("world"); + m_serverToJoin = parser.value("server"); + m_worldToJoin = parser.value("world"); m_profileToUse = parser.value("profile"); m_liveCheck = parser.isSet("alive"); @@ -267,7 +267,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) } // error if --launch is missing with --server or --profile - if (((!m_server_to_join.isEmpty() || !m_world_to_join.isEmpty()) || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { + if (((!m_serverToJoin.isEmpty() || !m_worldToJoin.isEmpty()) || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl; m_status = Application::Failed; return; @@ -385,10 +385,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) launch.command = "launch"; launch.args["id"] = m_instanceIdToLaunch; - if (!m_server_to_join.isEmpty()) { - launch.args["server"] = m_server_to_join; - } else if (!m_world_to_join.isEmpty()) { - launch.args["world"] = m_world_to_join; + if (!m_serverToJoin.isEmpty()) { + launch.args["server"] = m_serverToJoin; + } else if (!m_worldToJoin.isEmpty()) { + launch.args["world"] = m_worldToJoin; } if (!m_profileToUse.isEmpty()) { launch.args["profile"] = m_profileToUse; @@ -525,10 +525,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) if (!m_instanceIdToLaunch.isEmpty()) { qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch; } - if (!m_server_to_join.isEmpty()) { - qDebug() << "Address of server to join :" << m_server_to_join; - } else if (!m_world_to_join.isEmpty()) { - qDebug() << "Name of the world to join :" << m_world_to_join; + if (!m_serverToJoin.isEmpty()) { + qDebug() << "Address of server to join :" << m_serverToJoin; + } else if (!m_worldToJoin.isEmpty()) { + qDebug() << "Name of the world to join :" << m_worldToJoin; } qDebug() << "<> Paths set."; } @@ -1167,13 +1167,13 @@ void Application::performMainStartupAction() MinecraftAccountPtr accountToUse = nullptr; qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching"; - if (!m_server_to_join.isEmpty()) { + if (!m_serverToJoin.isEmpty()) { // FIXME: validate the server string - targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_server_to_join, false))); - qDebug() << " Launching with server" << m_server_to_join; - } else if (!m_world_to_join.isEmpty()) { - targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_world_to_join, true))); - qDebug() << " Launching with world" << m_world_to_join; + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_serverToJoin, false))); + qDebug() << " Launching with server" << m_serverToJoin; + } else if (!m_worldToJoin.isEmpty()) { + targetToJoin.reset(new MinecraftTarget(MinecraftTarget::parse(m_worldToJoin, true))); + qDebug() << " Launching with world" << m_worldToJoin; } if (!m_profileToUse.isEmpty()) { diff --git a/launcher/Application.h b/launcher/Application.h index fb54b1005..3bb20125e 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -289,8 +289,8 @@ class Application : public QApplication { QString m_detectedGLFWPath; QString m_detectedOpenALPath; QString m_instanceIdToLaunch; - QString m_server_to_join; - QString m_world_to_join; + QString m_serverToJoin; + QString m_worldToJoin; QString m_profileToUse; bool m_liveCheck = false; QList m_urlsToImport; diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 83bf3838e..73800574f 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -324,7 +324,7 @@ void LaunchController::launchInstance() return; } - m_launcher = m_instance->createLaunchTask(m_session, m_target_to_join); + m_launcher = m_instance->createLaunchTask(m_session, m_targetToJoin); if (!m_launcher) { emitFailed(tr("Couldn't instantiate a launcher.")); return; diff --git a/launcher/LaunchController.h b/launcher/LaunchController.h index e620b8c62..6e2a94258 100644 --- a/launcher/LaunchController.h +++ b/launcher/LaunchController.h @@ -62,7 +62,7 @@ class LaunchController : public Task { void setParentWidget(QWidget* widget) { m_parentWidget = widget; } - void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_target_to_join = std::move(targetToJoin); } + void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_targetToJoin = std::move(targetToJoin); } void setAccountToUse(MinecraftAccountPtr accountToUse) { m_accountToUse = std::move(accountToUse); } @@ -94,5 +94,5 @@ class LaunchController : public Task { MinecraftAccountPtr m_accountToUse = nullptr; AuthSessionPtr m_session; shared_qobject_ptr m_launcher; - MinecraftTarget::Ptr m_target_to_join; + MinecraftTarget::Ptr m_targetToJoin; }; diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index c50d57513..baebf8506 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -803,6 +803,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr auto profile = m_components->getProfile(); + // traits auto alltraits = traits(); if (alltraits.size()) { out << "Traits:"; @@ -812,6 +813,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << ""; } + // native libraries auto settings = this->settings(); bool nativeOpenAL = settings->get("UseNativeOpenAL").toBool(); bool nativeGLFW = settings->get("UseNativeGLFW").toBool(); @@ -847,6 +849,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << ""; } + // mods and core mods auto printModList = [&](const QString& label, ModFolderModel& model) { if (model.size()) { out << QString("%1:").arg(label); @@ -875,6 +878,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr printModList("Mods", *(loaderModList().get())); printModList("Core Mods", *(coreModList().get())); + // jar mods auto& jarMods = profile->getJarMods(); if (jarMods.size()) { out << "Jar Mods:"; @@ -890,11 +894,13 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << ""; } + // minecraft arguments auto params = processMinecraftArgs(nullptr, targetToJoin); out << "Params:"; out << " " + params.join(' '); out << ""; + // window size QString windowParams; if (settings->get("LaunchMaximized").toBool()) { out << "Window size: max (if available)"; diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index be1bde464..2b932ae47 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -90,7 +90,7 @@ void LauncherPartLaunch::executeTask() } } - m_launchScript = minecraftInstance->createLaunchScript(m_session, m_target_to_join); + m_launchScript = minecraftInstance->createLaunchScript(m_session, m_targetToJoin); QStringList args = minecraftInstance->javaArguments(); QString allArgs = args.join(", "); emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::Launcher); diff --git a/launcher/minecraft/launch/LauncherPartLaunch.h b/launcher/minecraft/launch/LauncherPartLaunch.h index ca0906550..ea125aa9e 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.h +++ b/launcher/minecraft/launch/LauncherPartLaunch.h @@ -34,7 +34,7 @@ class LauncherPartLaunch : public LaunchStep { void setWorkingDirectory(const QString& wd); void setAuthSession(AuthSessionPtr session) { m_session = session; } - void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_target_to_join = std::move(targetToJoin); } + void setTargetToJoin(MinecraftTarget::Ptr targetToJoin) { m_targetToJoin = std::move(targetToJoin); } private slots: void on_state(LoggedProcess::State state); @@ -44,7 +44,7 @@ class LauncherPartLaunch : public LaunchStep { QString m_command; AuthSessionPtr m_session; QString m_launchScript; - MinecraftTarget::Ptr m_target_to_join; + MinecraftTarget::Ptr m_targetToJoin; bool mayProceed = false; }; diff --git a/launcher/minecraft/launch/PrintInstanceInfo.cpp b/launcher/minecraft/launch/PrintInstanceInfo.cpp index 78cb26378..e44d09839 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.cpp +++ b/launcher/minecraft/launch/PrintInstanceInfo.cpp @@ -129,6 +129,6 @@ void PrintInstanceInfo::executeTask() #endif logLines(log, MessageLevel::Launcher); - logLines(instance->verboseDescription(m_session, m_target_to_join), MessageLevel::Launcher); + logLines(instance->verboseDescription(m_session, m_targetToJoin), MessageLevel::Launcher); emitSucceeded(); } diff --git a/launcher/minecraft/launch/PrintInstanceInfo.h b/launcher/minecraft/launch/PrintInstanceInfo.h index 780ac5b2c..4138c0cd2 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.h +++ b/launcher/minecraft/launch/PrintInstanceInfo.h @@ -24,7 +24,7 @@ class PrintInstanceInfo : public LaunchStep { Q_OBJECT public: explicit PrintInstanceInfo(LaunchTask* parent, AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) - : LaunchStep(parent), m_session(session), m_target_to_join(targetToJoin) {}; + : LaunchStep(parent), m_session(session), m_targetToJoin(targetToJoin) {}; virtual ~PrintInstanceInfo() = default; virtual void executeTask(); @@ -32,5 +32,5 @@ class PrintInstanceInfo : public LaunchStep { private: AuthSessionPtr m_session; - MinecraftTarget::Ptr m_target_to_join; + MinecraftTarget::Ptr m_targetToJoin; }; From c2192cfa987769375435f8f97e8a60cb46b5930f Mon Sep 17 00:00:00 2001 From: Tianhao Chai Date: Fri, 9 Aug 2024 14:11:44 -0400 Subject: [PATCH 102/120] mangohud support: getLibraryString should return absolute path when possible Some distros ship MangoHub vulkan layer json with bare shared object name instead of an absolute path. This breaks environment config as `MinecraftInstance::createLaunchEnvironment()` seems to require absolute path of `libMangoHud.so`. Since we already have `MangoHud::findLibrary()` lying around, use that to figure out where `libMangoHud.so` really is. In case of a platform that doesn't support `dlopen()`, fallback to old behavior and return the path verbatim as it is recorded in vk layer json. Signed-off-by: Tianhao Chai --- launcher/MangoHud.cpp | 30 +++++++++++++++++------- launcher/minecraft/MinecraftInstance.cpp | 2 +- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/launcher/MangoHud.cpp b/launcher/MangoHud.cpp index ab79f418b..ba16ddc4a 100644 --- a/launcher/MangoHud.cpp +++ b/launcher/MangoHud.cpp @@ -40,8 +40,8 @@ namespace MangoHud { QString getLibraryString() { - /* - * Check for vulkan layers in this order: + /** + * Guess MangoHud install location by searching for vulkan layers in this order: * * $VK_LAYER_PATH * $XDG_DATA_DIRS (/usr/local/share/:/usr/share/) @@ -49,8 +49,9 @@ QString getLibraryString() * /etc * $XDG_CONFIG_DIRS (/etc/xdg) * $XDG_CONFIG_HOME (~/.config) + * + * @returns Absolute path of libMangoHud.so if found and empty QString otherwise. */ - QStringList vkLayerList; { QString home = QDir::homePath(); @@ -85,7 +86,7 @@ QString getLibraryString() vkLayerList << FS::PathCombine(xdgConfigHome, "vulkan", "implicit_layer.d"); } - for (QString vkLayer : vkLayerList) { + for (const QString& vkLayer : vkLayerList) { // prefer to use architecture specific vulkan layers QString currentArch = QSysInfo::currentCpuArchitecture(); @@ -95,8 +96,8 @@ QString getLibraryString() QStringList manifestNames = { QString("MangoHud.%1.json").arg(currentArch), "MangoHud.json" }; - QString filePath = ""; - for (QString manifestName : manifestNames) { + QString filePath{}; + for (const QString& manifestName : manifestNames) { QString tryPath = FS::PathCombine(vkLayer, manifestName); if (QFile::exists(tryPath)) { filePath = tryPath; @@ -111,10 +112,23 @@ QString getLibraryString() auto conf = Json::requireDocument(filePath, vkLayer); auto confObject = Json::requireObject(conf, vkLayer); auto layer = Json::ensureObject(confObject, "layer"); - return Json::ensureString(layer, "library_path"); + QString libraryName = Json::ensureString(layer, "library_path"); + +#ifdef __GLIBC__ + // Check whether mangohud is usable on a glibc based system + if (!libraryName.isEmpty()) { + QString libraryPath = findLibrary(libraryName); + if (!libraryPath.isEmpty()) { + return libraryPath; + } + } +#else + // Without glibc return recorded shared library as-is. + return libraryName; +#endif } - return QString(); + return {}; } QString findLibrary(QString libName) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index d119104fe..6befad5d6 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -608,7 +608,7 @@ QProcessEnvironment MinecraftInstance::createLaunchEnvironment() // dlsym variant is only needed for OpenGL and not included in the vulkan layer appendLib("libMangoHud_dlsym.so"); appendLib("libMangoHud_opengl.so"); - appendLib(mangoHudLib.fileName()); + preloadList << mangoHudLibString; } env.insert("LD_PRELOAD", preloadList.join(QLatin1String(":"))); From 96dad63173667456e731bad3727e79fc7ee35c8e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 11 Aug 2024 00:22:53 +0000 Subject: [PATCH 103/120] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-parts': 'github:hercules-ci/flake-parts/9227223f6d922fee3c7b190b2cc238a99527bbb7?narHash=sha256-pQMhCCHyQGRzdfAkdJ4cIWiw%2BJNuWsTX7f0ZYSyz0VY%3D' (2024-07-03) → 'github:hercules-ci/flake-parts/8471fe90ad337a8074e957b69ca4d0089218391d?narHash=sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC%2Bx4%3D' (2024-08-01) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/7e7c39ea35c5cdd002cd4588b03a3fb9ece6fad9?narHash=sha256-EYekUHJE2gxeo2pM/zM9Wlqw1Uw2XTJXOSAO79ksc4Y%3D' (2024-07-12) → 'github:NixOS/nixpkgs/5e0ca22929f3342b19569b21b2f3462f053e497b?narHash=sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI%3D' (2024-08-09) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/8d6a17d0cdf411c55f12602624df6368ad86fac1?narHash=sha256-ni/87oHPZm6Gv0ECYxr1f6uxB0UKBWJ6HvS7lwLU6oY%3D' (2024-07-09) → 'github:cachix/pre-commit-hooks.nix/c7012d0c18567c889b948781bc74a501e92275d1?narHash=sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q%3D' (2024-08-09) --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 38b0d7430..1708a1e0a 100644 --- a/flake.lock +++ b/flake.lock @@ -23,11 +23,11 @@ ] }, "locked": { - "lastModified": 1719994518, - "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { @@ -75,11 +75,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1720768451, - "narHash": "sha256-EYekUHJE2gxeo2pM/zM9Wlqw1Uw2XTJXOSAO79ksc4Y=", + "lastModified": 1723175592, + "narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7e7c39ea35c5cdd002cd4588b03a3fb9ece6fad9", + "rev": "5e0ca22929f3342b19569b21b2f3462f053e497b", "type": "github" }, "original": { @@ -103,11 +103,11 @@ ] }, "locked": { - "lastModified": 1720524665, - "narHash": "sha256-ni/87oHPZm6Gv0ECYxr1f6uxB0UKBWJ6HvS7lwLU6oY=", + "lastModified": 1723202784, + "narHash": "sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "8d6a17d0cdf411c55f12602624df6368ad86fac1", + "rev": "c7012d0c18567c889b948781bc74a501e92275d1", "type": "github" }, "original": { From 6de026bfcf9cd29220e4d7f4a61cecacea86ad5d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 16 Aug 2024 14:34:28 +0300 Subject: [PATCH 104/120] replaced currentTextChanged with currentIndexChanged Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourcePage.cpp | 9 ++------- launcher/ui/pages/modplatform/ResourcePage.h | 2 +- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 6 +++--- launcher/ui/pages/modplatform/flame/FlamePage.h | 2 +- .../ui/pages/modplatform/flame/FlameResourcePages.cpp | 8 ++++---- launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp | 6 +++--- launcher/ui/pages/modplatform/modrinth/ModrinthPage.h | 2 +- .../pages/modplatform/modrinth/ModrinthResourcePages.cpp | 8 ++++---- 8 files changed, 19 insertions(+), 24 deletions(-) diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 4d01fb1f0..bed118465 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -321,14 +321,9 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI updateUi(); } -void ResourcePage::onVersionSelectionChanged(QString versionData) +void ResourcePage::onVersionSelectionChanged(int index) { - if (versionData.isNull() || versionData.isEmpty()) { - m_selected_version_index = -1; - return; - } - - m_selected_version_index = m_ui->versionSelectionBox->currentData().toInt(); + m_selected_version_index = index; updateSelectionButton(); } diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index d5214dd34..b625240eb 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -89,7 +89,7 @@ class ResourcePage : public QWidget, public BasePage { virtual void triggerSearch() = 0; void onSelectionChanged(QModelIndex first, QModelIndex second); - void onVersionSelectionChanged(QString data); + void onVersionSelectionChanged(int index); void onResourceSelected(); // NOTE: Can't use [[nodiscard]] here because of https://bugreports.qt.io/browse/QTBUG-58628 on Qt 5.12 diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 2c10dd085..850941269 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -84,7 +84,7 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlamePage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlamePage::onVersionSelectionChanged); + connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlamePage::onVersionSelectionChanged); ui->packView->setItemDelegate(new ProjectItemDelegate(this)); ui->packDescription->setMetaEntry("FlamePacks"); @@ -240,12 +240,12 @@ void FlamePage::suggestCurrent() [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } -void FlamePage::onVersionSelectionChanged(QString version) +void FlamePage::onVersionSelectionChanged(int index) { bool is_blocked = false; ui->versionSelectionBox->currentData().toInt(&is_blocked); - if (version.isNull() || version.isEmpty() || is_blocked) { + if (index == -1 || is_blocked) { m_selected_version_index = -1; return; } diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index d35858fbc..7590e1a95 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -78,7 +78,7 @@ class FlamePage : public QWidget, public BasePage { private slots: void triggerSearch(); void onSelectionChanged(QModelIndex first, QModelIndex second); - void onVersionSelectionChanged(QString data); + void onVersionSelectionChanged(int index); private: Ui::FlamePage* ui = nullptr; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index d82c76c3a..ffcf08b71 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -60,7 +60,7 @@ FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameModPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameModPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameModPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -94,7 +94,7 @@ FlameResourcePackPage::FlameResourcePackPage(ResourcePackDownloadDialog* dialog, // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameResourcePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameResourcePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameResourcePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -128,7 +128,7 @@ FlameTexturePackPage::FlameTexturePackPage(TexturePackDownloadDialog* dialog, Ba // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameTexturePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameTexturePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameTexturePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -162,7 +162,7 @@ FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseI // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameShaderPackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameShaderPackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameShaderPackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index cb811e428..937f8f670 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -85,7 +85,7 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthPage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthPage::onVersionSelectionChanged); + connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthPage::onVersionSelectionChanged); ui->packView->setItemDelegate(new ProjectItemDelegate(this)); ui->packDescription->setMetaEntry(metaEntryBase()); @@ -342,9 +342,9 @@ void ModrinthPage::triggerSearch() m_fetch_progress.watch(m_model->activeSearchJob().get()); } -void ModrinthPage::onVersionSelectionChanged(QString version) +void ModrinthPage::onVersionSelectionChanged(int index) { - if (version.isNull() || version.isEmpty()) { + if (index == -1) { selectedVersion = ""; return; } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index 4240dcafb..dadaeb0a0 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -80,7 +80,7 @@ class ModrinthPage : public QWidget, public BasePage { private slots: void onSelectionChanged(QModelIndex first, QModelIndex second); - void onVersionSelectionChanged(QString data); + void onVersionSelectionChanged(int index); void triggerSearch(); private: diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index 26fe46a54..6d3abca8f 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -58,7 +58,7 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instan // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthModPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthModPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthModPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -76,7 +76,7 @@ ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* d // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthResourcePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthResourcePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthResourcePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -94,7 +94,7 @@ ModrinthTexturePackPage::ModrinthTexturePackPage(TexturePackDownloadDialog* dial // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthTexturePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthTexturePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthTexturePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -112,7 +112,7 @@ ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthShaderPackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthShaderPackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthShaderPackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); From e6bc61d6d01e84e5c42ed9b779eeb1566a784a86 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 16 Aug 2024 14:44:57 +0300 Subject: [PATCH 105/120] add overload for qt5 Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 2 +- .../pages/modplatform/flame/FlameResourcePages.cpp | 11 +++++++---- .../ui/pages/modplatform/modrinth/ModrinthPage.cpp | 2 +- .../modplatform/modrinth/ModrinthResourcePages.cpp | 12 ++++++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 850941269..c8972aa2e 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -84,7 +84,7 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlamePage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlamePage::onVersionSelectionChanged); + connect(ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, &FlamePage::onVersionSelectionChanged); ui->packView->setItemDelegate(new ProjectItemDelegate(this)); ui->packDescription->setMetaEntry("FlamePacks"); diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index ffcf08b71..62c22902e 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -60,7 +60,7 @@ FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameModPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, &FlameModPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameModPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -94,7 +94,8 @@ FlameResourcePackPage::FlameResourcePackPage(ResourcePackDownloadDialog* dialog, // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameResourcePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &FlameResourcePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameResourcePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -128,7 +129,8 @@ FlameTexturePackPage::FlameTexturePackPage(TexturePackDownloadDialog* dialog, Ba // so it's best not to connect them in the parent's contructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameTexturePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &FlameTexturePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameTexturePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -162,7 +164,8 @@ FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseI // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &FlameShaderPackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &FlameShaderPackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameShaderPackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 937f8f670..03461d85a 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -85,7 +85,7 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthPage::onSelectionChanged); - connect(ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthPage::onVersionSelectionChanged); + connect(ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ModrinthPage::onVersionSelectionChanged); ui->packView->setItemDelegate(new ProjectItemDelegate(this)); ui->packDescription->setMetaEntry(metaEntryBase()); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index 6d3abca8f..85dcde471 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -58,7 +58,8 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instan // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthModPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthModPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ModrinthModPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthModPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -76,7 +77,8 @@ ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* d // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthResourcePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthResourcePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ModrinthResourcePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthResourcePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -94,7 +96,8 @@ ModrinthTexturePackPage::ModrinthTexturePackPage(TexturePackDownloadDialog* dial // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthTexturePackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthTexturePackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ModrinthTexturePackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthTexturePackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); @@ -112,7 +115,8 @@ ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, // so it's best not to connect them in the parent's constructor... connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthShaderPackPage::onSelectionChanged); - connect(m_ui->versionSelectionBox, &QComboBox::currentIndexChanged, this, &ModrinthShaderPackPage::onVersionSelectionChanged); + connect(m_ui->versionSelectionBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ModrinthShaderPackPage::onVersionSelectionChanged); connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthShaderPackPage::onResourceSelected); m_ui->packDescription->setMetaEntry(metaEntryBase()); From b0cd412926346496488c5e7cbfba0c2728ce2b0b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 16 Aug 2024 15:41:31 +0300 Subject: [PATCH 106/120] use index instead of currentIndex function Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index c8972aa2e..decb5de3b 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -250,7 +250,7 @@ void FlamePage::onVersionSelectionChanged(int index) return; } - m_selected_version_index = ui->versionSelectionBox->currentIndex(); + m_selected_version_index = index; Q_ASSERT(current.versions.at(m_selected_version_index).downloadUrl == ui->versionSelectionBox->currentData().toString()); From 91d6465d45210302ceab0f87cb5ad94b20fad487 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 18 Aug 2024 00:22:22 +0000 Subject: [PATCH 107/120] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/5e0ca22929f3342b19569b21b2f3462f053e497b?narHash=sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI%3D' (2024-08-09) → 'github:NixOS/nixpkgs/c3aa7b8938b17aebd2deecf7be0636000d62a2b9?narHash=sha256-med8%2B5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c%3D' (2024-08-14) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/c7012d0c18567c889b948781bc74a501e92275d1?narHash=sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q%3D' (2024-08-09) → 'github:cachix/pre-commit-hooks.nix/bfef0ada09e2c8ac55bbcd0831bd0c9d42e651ba?narHash=sha256-yezvUuFiEnCFbGuwj/bQcqg7RykIEqudOy/RBrId0pc%3D' (2024-08-16) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 1708a1e0a..77e707692 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1723175592, - "narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=", + "lastModified": 1723637854, + "narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5e0ca22929f3342b19569b21b2f3462f053e497b", + "rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9", "type": "github" }, "original": { @@ -103,11 +103,11 @@ ] }, "locked": { - "lastModified": 1723202784, - "narHash": "sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q=", + "lastModified": 1723803910, + "narHash": "sha256-yezvUuFiEnCFbGuwj/bQcqg7RykIEqudOy/RBrId0pc=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "c7012d0c18567c889b948781bc74a501e92275d1", + "rev": "bfef0ada09e2c8ac55bbcd0831bd0c9d42e651ba", "type": "github" }, "original": { From 6bd8b72f68f4dd52d746e8ffc7e503ad985fd2b0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Aug 2024 22:38:45 +0300 Subject: [PATCH 108/120] fix meta not validating for specific versions Signed-off-by: Trial97 --- launcher/meta/BaseEntity.cpp | 38 +++++++++++++++++++++++++---------- launcher/meta/Version.h | 2 +- launcher/meta/VersionList.cpp | 2 ++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 24bced3a8..b0e754ada 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -15,6 +15,7 @@ #include "BaseEntity.h" +#include "Exception.h" #include "FileSystem.h" #include "Json.h" #include "modplatform/helpers/HashUtils.h" @@ -91,7 +92,8 @@ Task::Ptr BaseEntity::loadTask(Net::Mode mode) bool BaseEntity::isLoaded() const { - return m_load_status != LoadStatus::NotLoaded; + // consider it loaded only if the main hash is either empty and was remote loadded or the hashes match and was loaded + return m_sha256.isEmpty() ? m_load_status == LoadStatus::Remote : m_load_status != LoadStatus::NotLoaded && m_sha256 == m_file_sha256; } void BaseEntity::setSha256(QString sha256) @@ -109,30 +111,44 @@ BaseEntityLoadTask::BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode) : m_e void BaseEntityLoadTask::executeTask() { const QString fname = QDir("meta").absoluteFilePath(m_entity->localFilename()); - // load local file if nothing is loaded yet - if (m_entity->m_load_status == BaseEntity::LoadStatus::NotLoaded && QFile::exists(fname)) { - setStatus(tr("Loading local file")); + auto hashMatches = false; + // the file exists on disk try to load it + if (QFile::exists(fname)) { try { - auto fileData = FS::read(fname); - m_entity->m_file_sha256 = Hashing::hash(fileData, Hashing::Algorithm::Sha256); - if (m_mode == Net::Mode::Online && !m_entity->m_sha256.isEmpty() && m_entity->m_sha256 != m_entity->m_file_sha256) { - FS::deletePath(fname); - } else { + QByteArray fileData; + // read local file if nothing is loaded yet + if (m_entity->m_load_status == BaseEntity::LoadStatus::NotLoaded || m_entity->m_file_sha256.isEmpty()) { + setStatus(tr("Loading local file")); + fileData = FS::read(fname); + m_entity->m_file_sha256 = Hashing::hash(fileData, Hashing::Algorithm::Sha256); + } + + // on online the hash needs to match + hashMatches = m_entity->m_sha256 == m_entity->m_file_sha256; + if (m_mode == Net::Mode::Online && !m_entity->m_sha256.isEmpty() && !hashMatches) { + throw Exception("mismatched checksum"); + } + + // load local file + if (m_entity->m_load_status == BaseEntity::LoadStatus::NotLoaded) { auto doc = Json::requireDocument(fileData, fname); auto obj = Json::requireObject(doc, fname); m_entity->parse(obj); m_entity->m_load_status = BaseEntity::LoadStatus::Local; } + } catch (const Exception& e) { qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause()); // just make sure it's gone and we never consider it again. FS::deletePath(fname); + m_entity->m_load_status = BaseEntity::LoadStatus::NotLoaded; } } // if we need remote update, run the update task - auto hashMatches = !m_entity->m_sha256.isEmpty() && m_entity->m_sha256 == m_entity->m_file_sha256; auto wasLoadedOffline = m_entity->m_load_status != BaseEntity::LoadStatus::NotLoaded && m_mode == Net::Mode::Offline; - if (wasLoadedOffline || hashMatches) { + // if has is not present allways fetch from remote(e.g. the main index file), else only fetch if hash doesn't match + auto wasLoadedRemote = m_entity->m_sha256.isEmpty() ? m_entity->m_load_status == BaseEntity::LoadStatus::Remote : hashMatches; + if (wasLoadedOffline || wasLoadedRemote) { emitSucceeded(); return; } diff --git a/launcher/meta/Version.h b/launcher/meta/Version.h index 149af86f6..46dc740da 100644 --- a/launcher/meta/Version.h +++ b/launcher/meta/Version.h @@ -52,7 +52,7 @@ class Version : public QObject, public BaseVersion, public BaseEntity { const Meta::RequireSet& requiredSet() const { return m_requires; } VersionFilePtr data() const { return m_data; } bool isRecommended() const { return m_recommended; } - bool isLoaded() const { return m_data != nullptr; } + bool isLoaded() const { return m_data != nullptr && BaseEntity::isLoaded(); } void merge(const Version::Ptr& other); void mergeFromList(const Version::Ptr& other); diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index f21e4594a..698c73ef4 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -139,6 +139,8 @@ Version::Ptr VersionList::getVersion(const QString& version) if (!out) { out = std::make_shared(m_uid, version); m_lookup[version] = out; + setupAddedVersion(m_versions.size(), out); + m_versions.append(out); } return out; } From 7a6627683895fab64f99a87e6b054614ff083f90 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 20 Aug 2024 01:07:23 +0300 Subject: [PATCH 109/120] fix conflicts Signed-off-by: Trial97 --- launcher/minecraft/launch/AutoInstallJava.cpp | 12 +++++++++--- launcher/ui/java/VersionList.cpp | 3 +-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index eefed9cf5..d43f41ddb 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -121,6 +121,9 @@ void AutoInstallJava::executeTask() 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(); } @@ -213,11 +216,11 @@ void AutoInstallJava::tryNextMajorJava() m_majorJavaVersionIndex++; auto javaMajor = versionList->getVersion(QString("java%1").arg(majorJavaVersion)); - javaMajor->load(Net::Mode::Online); - m_current_task = javaMajor->getCurrentTask(); - if (javaMajor->isLoaded() || !m_current_task) { + + if (javaMajor->isLoaded()) { downloadJava(javaMajor, wantedJavaName); } else { + m_current_task = APPLICATION->metadataIndex()->loadVersion("net.minecraft.java", javaMajor->version(), 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); @@ -225,6 +228,9 @@ void AutoInstallJava::tryNextMajorJava() 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() diff --git a/launcher/ui/java/VersionList.cpp b/launcher/ui/java/VersionList.cpp index 6f60a6867..f2c0cb3b9 100644 --- a/launcher/ui/java/VersionList.cpp +++ b/launcher/ui/java/VersionList.cpp @@ -35,8 +35,7 @@ VersionList::VersionList(Meta::Version::Ptr version, QObject* parent) : BaseVers Task::Ptr VersionList::getLoadTask() { - m_version->load(Net::Mode::Online); - auto task = m_version->getCurrentTask(); + auto task = m_version->loadTask(Net::Mode::Online); connect(task.get(), &Task::finished, this, &VersionList::sortVersions); return task; } From ca298d1ed5cffb9a92dc78523a72ee407a673694 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 20 Aug 2024 01:08:03 +0300 Subject: [PATCH 110/120] add automatic java switch on minecraft version switch Signed-off-by: Trial97 --- launcher/minecraft/MinecraftInstance.cpp | 1 + launcher/minecraft/launch/AutoInstallJava.cpp | 1 + launcher/ui/pages/instance/InstanceSettingsPage.cpp | 3 +++ launcher/ui/pages/instance/VersionPage.cpp | 5 +++++ 4 files changed, 10 insertions(+) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 3963b0148..d861056bf 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -138,6 +138,7 @@ void MinecraftInstance::loadSpecificSettings() // Java Settings auto locationOverride = m_settings->registerSetting("OverrideJavaLocation", false); auto argsOverride = m_settings->registerSetting("OverrideJavaArgs", false); + m_settings->registerSetting("AutomaticJava", false); if (auto global_settings = globalSettings()) { m_settings->registerOverride(global_settings->getSetting("JavaPath"), locationOverride); diff --git a/launcher/minecraft/launch/AutoInstallJava.cpp b/launcher/minecraft/launch/AutoInstallJava.cpp index d43f41ddb..3f58a28a6 100644 --- a/launcher/minecraft/launch/AutoInstallJava.cpp +++ b/launcher/minecraft/launch/AutoInstallJava.cpp @@ -132,6 +132,7 @@ 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::Info); emitSucceeded(); } diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 56c3e2b9a..19bc9fdf9 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -38,6 +38,7 @@ #include "InstanceSettingsPage.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/WorldList.h" +#include "settings/Setting.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/java/InstallJavaDialog.h" #include "ui_InstanceSettingsPage.h" @@ -346,6 +347,8 @@ void InstanceSettingsPage::loadSettings() bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool(); bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool(); + connect(m_settings->getSetting("OverrideJavaLocation").get(), &Setting::SettingChanged, ui->javaSettingsGroupBox, + [this] { ui->javaSettingsGroupBox->setChecked(m_settings->get("OverrideJavaLocation").toBool()); }); ui->javaSettingsGroupBox->setChecked(overrideLocation); ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString()); ui->skipCompatibilityCheckbox->setChecked(m_settings->get("IgnoreJavaCompatibility").toBool()); diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 807bc5d58..c55d32efb 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -393,6 +393,11 @@ void VersionPage::on_actionChange_version_triggered() bool important = false; if (uid == "net.minecraft") { important = true; + if (APPLICATION->settings()->get("AutomaticJavaSwitch").toBool() && m_inst->settings()->get("AutomaticJava").toBool() && + m_inst->settings()->get("OverrideJavaLocation").toBool()) { + m_inst->settings()->set("OverrideJavaLocation", false); + m_inst->settings()->set("JavaPath", ""); + } } m_profile->setComponentVersion(uid, vselect.selectedVersion()->descriptor(), important); m_profile->resolve(Net::Mode::Online); From 002fc71b8d65dd0800eda24385a6a8e6b98af5bd Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 20 Aug 2024 01:18:37 +0300 Subject: [PATCH 111/120] allways load java list on autodetect Signed-off-by: Trial97 --- launcher/ui/dialogs/VersionSelectDialog.cpp | 2 +- launcher/ui/dialogs/VersionSelectDialog.h | 2 +- launcher/ui/widgets/VersionSelectWidget.cpp | 4 ++-- launcher/ui/widgets/VersionSelectWidget.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index c61d10578..876d7470e 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -121,7 +121,7 @@ void VersionSelectDialog::setResizeOn(int column) int VersionSelectDialog::exec() { QDialog::open(); - m_versionWidget->initialize(m_vlist); + m_versionWidget->initialize(m_vlist, true); m_versionWidget->selectSearch(); if (resizeOnColumn != -1) { m_versionWidget->setResizeOn(resizeOnColumn); diff --git a/launcher/ui/dialogs/VersionSelectDialog.h b/launcher/ui/dialogs/VersionSelectDialog.h index 34c5e66f8..65ea64fd9 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.h +++ b/launcher/ui/dialogs/VersionSelectDialog.h @@ -37,7 +37,7 @@ class VersionSelectDialog : public QDialog { public: explicit VersionSelectDialog(BaseVersionList* vlist, QString title, QWidget* parent = 0, bool cancelable = true); - virtual ~VersionSelectDialog() {}; + virtual ~VersionSelectDialog() = default; int exec() override; diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index 1a62e689b..2d735d18f 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -105,14 +105,14 @@ bool VersionSelectWidget::eventFilter(QObject* watched, QEvent* event) return QObject::eventFilter(watched, event); } -void VersionSelectWidget::initialize(BaseVersionList* vlist) +void VersionSelectWidget::initialize(BaseVersionList* vlist, bool forceLoad) { m_vlist = vlist; m_proxyModel->setSourceModel(vlist); listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); - if (!m_vlist->isLoaded()) { + if (!m_vlist->isLoaded() || forceLoad) { loadList(); } else { if (m_proxyModel->rowCount() == 0) { diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index d8d8506ea..c16d4c0dd 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -54,7 +54,7 @@ class VersionSelectWidget : public QWidget { ~VersionSelectWidget(); //! loads the list if needed. - void initialize(BaseVersionList* vlist); + void initialize(BaseVersionList* vlist, bool forceLoad = false); //! Starts a task that loads the list. void loadList(); From da7cc529f05c5f2a7cd51d97c1865f70f62b9ec8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 21 Aug 2024 14:54:47 +0300 Subject: [PATCH 112/120] Enable auto-detect java if java path is not set Signed-off-by: Trial97 --- launcher/Application.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index a40222b41..9cd0445e6 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -647,8 +647,9 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("JvmArgs", ""); m_settings->registerSetting("IgnoreJavaCompatibility", false); m_settings->registerSetting("IgnoreJavaWizard", false); - m_settings->registerSetting("AutomaticJavaSwitch", false); - m_settings->registerSetting("AutomaticJavaDownload", false); + auto defaultEnableAutoJava = m_settings->get("JavaPath").toString().isEmpty(); + m_settings->registerSetting("AutomaticJavaSwitch", defaultEnableAutoJava); + m_settings->registerSetting("AutomaticJavaDownload", defaultEnableAutoJava); // Legacy settings m_settings->registerSetting("OnlineFixes", false); From 26ae6086855bdb4638c1033a03675df04eb4b852 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 21 Aug 2024 15:01:42 +0300 Subject: [PATCH 113/120] fix initial java dialog Signed-off-by: Trial97 --- launcher/ui/widgets/JavaSettingsWidget.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index fb90afe1d..bf58bf9f7 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -186,13 +186,9 @@ void JavaSettingsWidget::initialize() .arg(BuildConfig.LAUNCHER_DISPLAYNAME), QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) ->exec(); - if (button == QMessageBox::Yes) { - m_autodetectJavaCheckBox->setChecked(true); - m_autodownloadCheckBox->setChecked(true); - } else { - m_autodetectJavaCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool()); - m_autodownloadCheckBox->setChecked(s->get("AutomaticJavaSwitch").toBool() && s->get("AutomaticJavaDownload").toBool()); - } + auto checked = button == QMessageBox::Yes; + m_autodetectJavaCheckBox->setChecked(checked); + m_autodownloadCheckBox->setChecked(checked); } } From 7472233033762eb5446cd5beefcc603f54d0296b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 17:22:09 +0000 Subject: [PATCH 114/120] chore(deps): update korthout/backport-action action to v3.1.0 --- .github/workflows/backport.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index d91d9507a..4146cddf4 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -25,7 +25,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs - uses: korthout/backport-action@v3.0.2 + uses: korthout/backport-action@v3.1.0 with: # Config README: https://github.com/korthout/backport-action#backport-action pull_description: |- From 2ad34c724e0cae50db9359147cb180aae15ab55d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 21 Aug 2024 22:11:43 +0100 Subject: [PATCH 115/120] Make log colours themeable Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 2 - launcher/ui/ColorCache.cpp | 32 --- launcher/ui/ColorCache.h | 106 ---------- launcher/ui/pages/global/LauncherPage.cpp | 64 +++--- launcher/ui/pages/global/LauncherPage.h | 3 - launcher/ui/pages/instance/LogPage.cpp | 37 ++-- launcher/ui/themes/BrightTheme.cpp | 5 - launcher/ui/themes/BrightTheme.h | 1 - launcher/ui/themes/CustomTheme.cpp | 234 ++++++++++------------ launcher/ui/themes/CustomTheme.h | 8 +- launcher/ui/themes/DarkTheme.cpp | 7 +- launcher/ui/themes/DarkTheme.h | 1 - launcher/ui/themes/ITheme.cpp | 31 ++- launcher/ui/themes/ITheme.h | 12 +- launcher/ui/themes/SystemTheme.cpp | 5 - launcher/ui/themes/SystemTheme.h | 1 - launcher/ui/themes/ThemeManager.cpp | 28 +-- launcher/ui/themes/ThemeManager.h | 9 +- 18 files changed, 230 insertions(+), 356 deletions(-) delete mode 100644 launcher/ui/ColorCache.cpp delete mode 100644 launcher/ui/ColorCache.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 719af84e6..98ef29452 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -784,8 +784,6 @@ SET(LAUNCHER_SOURCES # GUI - windows ui/GuiUtil.h ui/GuiUtil.cpp - ui/ColorCache.h - ui/ColorCache.cpp ui/MainWindow.h ui/MainWindow.cpp ui/InstanceWindow.h diff --git a/launcher/ui/ColorCache.cpp b/launcher/ui/ColorCache.cpp deleted file mode 100644 index f941a6093..000000000 --- a/launcher/ui/ColorCache.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "ColorCache.h" - -/** - * Blend the color with the front color, adapting to the back color - */ -QColor ColorCache::blend(QColor color) -{ - if (Rainbow::luma(m_front) > Rainbow::luma(m_back)) { - // for dark color schemes, produce a fitting color first - color = Rainbow::tint(m_front, color, 0.5); - } - // adapt contrast - return Rainbow::mix(m_front, color, m_bias); -} - -/** - * Blend the color with the back color - */ -QColor ColorCache::blendBackground(QColor color) -{ - // adapt contrast - return Rainbow::mix(m_back, color, m_bias); -} - -void ColorCache::recolorAll() -{ - auto iter = m_colors.begin(); - while (iter != m_colors.end()) { - iter->front = blend(iter->original); - iter->back = blendBackground(iter->original); - } -} diff --git a/launcher/ui/ColorCache.h b/launcher/ui/ColorCache.h deleted file mode 100644 index 1cf292c13..000000000 --- a/launcher/ui/ColorCache.h +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once -#include -#include -#include -#include - -class ColorCache { - public: - ColorCache(QColor front, QColor back, qreal bias) - { - m_front = front; - m_back = back; - m_bias = bias; - }; - - void addColor(int key, QColor color) { m_colors[key] = { color, blend(color), blendBackground(color) }; } - - void setForeground(QColor front) - { - if (m_front != front) { - m_front = front; - recolorAll(); - } - } - - void setBackground(QColor back) - { - if (m_back != back) { - m_back = back; - recolorAll(); - } - } - - QColor getFront(int key) - { - auto iter = m_colors.find(key); - if (iter == m_colors.end()) { - return QColor(); - } - return (*iter).front; - } - - QColor getBack(int key) - { - auto iter = m_colors.find(key); - if (iter == m_colors.end()) { - return QColor(); - } - return (*iter).back; - } - - /** - * Blend the color with the front color, adapting to the back color - */ - QColor blend(QColor color); - - /** - * Blend the color with the back color - */ - QColor blendBackground(QColor color); - - protected: - void recolorAll(); - - protected: - struct ColorEntry { - QColor original; - QColor front; - QColor back; - }; - - protected: - qreal m_bias; - QColor m_front; - QColor m_back; - QMap m_colors; -}; - -class LogColorCache : public ColorCache { - public: - LogColorCache(QColor front, QColor back) : ColorCache(front, back, 1.0) - { - addColor((int)MessageLevel::Launcher, QColor("purple")); - addColor((int)MessageLevel::Debug, QColor("green")); - addColor((int)MessageLevel::Warning, QColor("orange")); - addColor((int)MessageLevel::Error, QColor("red")); - addColor((int)MessageLevel::Fatal, QColor("red")); - addColor((int)MessageLevel::Message, front); - } - - QColor getFront(MessageLevel::Enum level) - { - if (!m_colors.contains((int)level)) { - return ColorCache::getFront((int)MessageLevel::Message); - } - return ColorCache::getFront((int)level); - } - - QColor getBack(MessageLevel::Enum level) - { - if (level == MessageLevel::Fatal) { - return QColor(Qt::black); - } - return QColor(Qt::transparent); - } -}; diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 6a240389a..2f2ce6f70 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -4,6 +4,7 @@ * Copyright (c) 2022 Jamie Mansfield * Copyright (c) 2022 dada513 * Copyright (C) 2022 Tayou + * Copyright (C) 2024 TheKodeToad * * 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 @@ -50,6 +51,7 @@ #include "DesktopServices.h" #include "settings/SettingsObject.h" #include "ui/themes/ITheme.h" +#include "ui/themes/ThemeManager.h" #include "updater/ExternalUpdater.h" #include @@ -66,9 +68,6 @@ enum InstSortMode { LauncherPage::LauncherPage(QWidget* parent) : QWidget(parent), ui(new Ui::LauncherPage) { ui->setupUi(this); - auto origForeground = ui->fontPreview->palette().color(ui->fontPreview->foregroundRole()); - auto origBackground = ui->fontPreview->palette().color(ui->fontPreview->backgroundRole()); - m_colors.reset(new LogColorCache(origForeground, origBackground)); ui->sortingModeGroup->setId(ui->sortByNameBtn, Sort_Name); ui->sortingModeGroup->setId(ui->sortLastLaunchedBtn, Sort_LastLaunch); @@ -80,8 +79,9 @@ LauncherPage::LauncherPage(QWidget* parent) : QWidget(parent), ui(new Ui::Launch ui->updateSettingsBox->setHidden(!APPLICATION->updater()); - connect(ui->fontSizeBox, SIGNAL(valueChanged(int)), SLOT(refreshFontPreview())); - connect(ui->consoleFont, SIGNAL(currentFontChanged(QFont)), SLOT(refreshFontPreview())); + connect(ui->fontSizeBox, QOverload::of(&QSpinBox::valueChanged), this, &LauncherPage::refreshFontPreview); + connect(ui->consoleFont, &QFontComboBox::currentFontChanged, this, &LauncherPage::refreshFontPreview); + connect(ui->themeCustomizationWidget, &ThemeCustomizationWidget::currentWidgetThemeChanged, this, &LauncherPage::refreshFontPreview); connect(ui->themeCustomizationWidget, &ThemeCustomizationWidget::currentCatChanged, APPLICATION, &Application::currentCatChanged); } @@ -311,37 +311,47 @@ void LauncherPage::loadSettings() void LauncherPage::refreshFontPreview() { + const LogColors& colors = APPLICATION->themeManager()->getLogColors(); + int fontSize = ui->fontSizeBox->value(); QString fontFamily = ui->consoleFont->currentFont().family(); ui->fontPreview->clear(); defaultFormat->setFont(QFont(fontFamily, fontSize)); - { + + auto print = [this, colors](const QString& message, MessageLevel::Enum level) { QTextCharFormat format(*defaultFormat); - format.setForeground(m_colors->getFront(MessageLevel::Error)); + + QColor bg = colors.background.value(level); + QColor fg = colors.foreground.value(level); + + if (bg.isValid()) + format.setBackground(bg); + + if (fg.isValid()) + format.setForeground(fg); + // append a paragraph/line auto workCursor = ui->fontPreview->textCursor(); workCursor.movePosition(QTextCursor::End); - workCursor.insertText(tr("[Something/ERROR] A spooky error!"), format); + workCursor.insertText(message, format); workCursor.insertBlock(); - } - { - QTextCharFormat format(*defaultFormat); - format.setForeground(m_colors->getFront(MessageLevel::Message)); - // append a paragraph/line - auto workCursor = ui->fontPreview->textCursor(); - workCursor.movePosition(QTextCursor::End); - workCursor.insertText(tr("[Test/INFO] A harmless message..."), format); - workCursor.insertBlock(); - } - { - QTextCharFormat format(*defaultFormat); - format.setForeground(m_colors->getFront(MessageLevel::Warning)); - // append a paragraph/line - auto workCursor = ui->fontPreview->textCursor(); - workCursor.movePosition(QTextCursor::End); - workCursor.insertText(tr("[Something/WARN] A not so spooky warning."), format); - workCursor.insertBlock(); - } + }; + + print(QString("%1 version: %2 (%3)\n") + .arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString(), BuildConfig.BUILD_PLATFORM), + MessageLevel::Launcher); + + QDate today = QDate::currentDate(); + + if (today.month() == 10 && today.day() == 31) + print(tr("[Test/ERROR] OOoooOOOoooo! A spooky error!"), MessageLevel::Error); + else + print(tr("[Test/ERROR] A spooky error!"), MessageLevel::Error); + + print(tr("[Test/INFO] A harmless message..."), MessageLevel::Info); + print(tr("[Test/WARN] A not so spooky warning."), MessageLevel::Warning); + print(tr("[Test/DEBUG] A secret debugging message..."), MessageLevel::Debug); + print(tr("[Test/FATAL] A terrifying fatal error!"), MessageLevel::Fatal); } void LauncherPage::retranslate() diff --git a/launcher/ui/pages/global/LauncherPage.h b/launcher/ui/pages/global/LauncherPage.h index f9aefb171..4a46d1e48 100644 --- a/launcher/ui/pages/global/LauncherPage.h +++ b/launcher/ui/pages/global/LauncherPage.h @@ -41,7 +41,6 @@ #include #include #include "java/JavaChecker.h" -#include "ui/ColorCache.h" #include "ui/pages/BasePage.h" class QTextCharFormat; @@ -93,7 +92,5 @@ class LauncherPage : public QWidget, public BasePage { // default format for the font preview... QTextCharFormat* defaultFormat; - std::unique_ptr m_colors; - std::shared_ptr m_languageModel; }; diff --git a/launcher/ui/pages/instance/LogPage.cpp b/launcher/ui/pages/instance/LogPage.cpp index 8e1e53762..0c22d1de6 100644 --- a/launcher/ui/pages/instance/LogPage.cpp +++ b/launcher/ui/pages/instance/LogPage.cpp @@ -3,7 +3,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2024 TheKodeToad * * 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 @@ -47,8 +47,8 @@ #include "launch/LaunchTask.h" #include "settings/Setting.h" -#include "ui/ColorCache.h" #include "ui/GuiUtil.h" +#include "ui/themes/ThemeManager.h" #include @@ -57,26 +57,36 @@ class LogFormatProxyModel : public QIdentityProxyModel { LogFormatProxyModel(QObject* parent = nullptr) : QIdentityProxyModel(parent) {} QVariant data(const QModelIndex& index, int role) const override { + const LogColors& colors = APPLICATION->themeManager()->getLogColors(); + switch (role) { case Qt::FontRole: return m_font; case Qt::ForegroundRole: { - MessageLevel::Enum level = (MessageLevel::Enum)QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); - return m_colors->getFront(level); + auto level = static_cast(QIdentityProxyModel::data(index, LogModel::LevelRole).toInt()); + QColor result = colors.foreground.value(level); + + if (result.isValid()) + return result; + + break; } case Qt::BackgroundRole: { - MessageLevel::Enum level = (MessageLevel::Enum)QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); - return m_colors->getBack(level); + auto level = static_cast(QIdentityProxyModel::data(index, LogModel::LevelRole).toInt()); + QColor result = colors.background.value(level); + + if (result.isValid()) + return result; + + break; } - default: - return QIdentityProxyModel::data(index, role); } + + return QIdentityProxyModel::data(index, role); } void setFont(QFont font) { m_font = font; } - void setColors(LogColorCache* colors) { m_colors.reset(colors); } - QModelIndex find(const QModelIndex& start, const QString& value, bool reverse) const { QModelIndex parentIndex = parent(start); @@ -125,7 +135,6 @@ class LogFormatProxyModel : public QIdentityProxyModel { private: QFont m_font; - std::unique_ptr m_colors; }; LogPage::LogPage(InstancePtr instance, QWidget* parent) : QWidget(parent), ui(new Ui::LogPage), m_instance(instance) @@ -134,12 +143,6 @@ LogPage::LogPage(InstancePtr instance, QWidget* parent) : QWidget(parent), ui(ne ui->tabWidget->tabBar()->hide(); m_proxy = new LogFormatProxyModel(this); - // set up text colors in the log proxy and adapt them to the current theme foreground and background - { - auto origForeground = ui->text->palette().color(ui->text->foregroundRole()); - auto origBackground = ui->text->palette().color(ui->text->backgroundRole()); - m_proxy->setColors(new LogColorCache(origForeground, origBackground)); - } // set up fonts in the log proxy { diff --git a/launcher/ui/themes/BrightTheme.cpp b/launcher/ui/themes/BrightTheme.cpp index 39a5bfd14..81bdd773e 100644 --- a/launcher/ui/themes/BrightTheme.cpp +++ b/launcher/ui/themes/BrightTheme.cpp @@ -46,11 +46,6 @@ QString BrightTheme::name() return QObject::tr("Bright"); } -bool BrightTheme::hasColorScheme() -{ - return true; -} - QPalette BrightTheme::colorScheme() { QPalette brightPalette; diff --git a/launcher/ui/themes/BrightTheme.h b/launcher/ui/themes/BrightTheme.h index 750e7bfc5..070eef124 100644 --- a/launcher/ui/themes/BrightTheme.h +++ b/launcher/ui/themes/BrightTheme.h @@ -45,7 +45,6 @@ class BrightTheme : public FusionTheme { QString tooltip() override; bool hasStyleSheet() override; QString appStyleSheet() override; - bool hasColorScheme() override; QPalette colorScheme() override; double fadeAmount() override; QColor fadeColor() override; diff --git a/launcher/ui/themes/CustomTheme.cpp b/launcher/ui/themes/CustomTheme.cpp index 22b366b62..081ba1900 100644 --- a/launcher/ui/themes/CustomTheme.cpp +++ b/launcher/ui/themes/CustomTheme.cpp @@ -2,6 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2024 Tayou + * Copyright (C) 2024 TheKodeToad * * 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 @@ -39,121 +40,6 @@ const char* themeFile = "theme.json"; -static bool readThemeJson(const QString& path, - QPalette& palette, - double& fadeAmount, - QColor& fadeColor, - QString& name, - QString& widgets, - QString& qssFilePath, - bool& dataIncomplete) -{ - QFileInfo pathInfo(path); - if (pathInfo.exists() && pathInfo.isFile()) { - try { - auto doc = Json::requireDocument(path, "Theme JSON file"); - const QJsonObject root = doc.object(); - dataIncomplete = !root.contains("qssFilePath"); - name = Json::requireString(root, "name", "Theme name"); - widgets = Json::requireString(root, "widgets", "Qt widget theme"); - qssFilePath = Json::ensureString(root, "qssFilePath", "themeStyle.css"); - auto colorsRoot = Json::requireObject(root, "colors", "colors object"); - auto readColor = [&](QString colorName) -> QColor { - auto colorValue = Json::ensureString(colorsRoot, colorName, QString()); - if (!colorValue.isEmpty()) { - QColor color(colorValue); - if (!color.isValid()) { - themeWarningLog() << "Color value" << colorValue << "for" << colorName << "was not recognized."; - return QColor(); - } - return color; - } - return QColor(); - }; - auto readAndSetColor = [&](QPalette::ColorRole role, QString colorName) { - auto color = readColor(colorName); - if (color.isValid()) { - palette.setColor(role, color); - } else { - themeDebugLog() << "Color value for" << colorName << "was not present."; - } - }; - - // palette - readAndSetColor(QPalette::Window, "Window"); - readAndSetColor(QPalette::WindowText, "WindowText"); - readAndSetColor(QPalette::Base, "Base"); - readAndSetColor(QPalette::AlternateBase, "AlternateBase"); - readAndSetColor(QPalette::ToolTipBase, "ToolTipBase"); - readAndSetColor(QPalette::ToolTipText, "ToolTipText"); - readAndSetColor(QPalette::Text, "Text"); - readAndSetColor(QPalette::Button, "Button"); - readAndSetColor(QPalette::ButtonText, "ButtonText"); - readAndSetColor(QPalette::BrightText, "BrightText"); - readAndSetColor(QPalette::Link, "Link"); - readAndSetColor(QPalette::Highlight, "Highlight"); - readAndSetColor(QPalette::HighlightedText, "HighlightedText"); - - // fade - fadeColor = readColor("fadeColor"); - fadeAmount = Json::ensureDouble(colorsRoot, "fadeAmount", 0.5, "fade amount"); - - } catch (const Exception& e) { - themeWarningLog() << "Couldn't load theme json: " << e.cause(); - return false; - } - } else { - themeDebugLog() << "No theme json present."; - return false; - } - return true; -} - -static bool writeThemeJson(const QString& path, - const QPalette& palette, - double fadeAmount, - QColor fadeColor, - QString name, - QString widgets, - QString qssFilePath) -{ - QJsonObject rootObj; - rootObj.insert("name", name); - rootObj.insert("widgets", widgets); - rootObj.insert("qssFilePath", qssFilePath); - - QJsonObject colorsObj; - auto insertColor = [&](QPalette::ColorRole role, QString colorName) { colorsObj.insert(colorName, palette.color(role).name()); }; - - // palette - insertColor(QPalette::Window, "Window"); - insertColor(QPalette::WindowText, "WindowText"); - insertColor(QPalette::Base, "Base"); - insertColor(QPalette::AlternateBase, "AlternateBase"); - insertColor(QPalette::ToolTipBase, "ToolTipBase"); - insertColor(QPalette::ToolTipText, "ToolTipText"); - insertColor(QPalette::Text, "Text"); - insertColor(QPalette::Button, "Button"); - insertColor(QPalette::ButtonText, "ButtonText"); - insertColor(QPalette::BrightText, "BrightText"); - insertColor(QPalette::Link, "Link"); - insertColor(QPalette::Highlight, "Highlight"); - insertColor(QPalette::HighlightedText, "HighlightedText"); - - // fade - colorsObj.insert("fadeColor", fadeColor.name()); - colorsObj.insert("fadeAmount", fadeAmount); - - rootObj.insert("colors", colorsObj); - try { - Json::write(rootObj, path); - return true; - } catch ([[maybe_unused]] const Exception& e) { - themeWarningLog() << "Failed to write theme json to" << path; - return false; - } -} - /// @param baseTheme Base Theme /// @param fileInfo FileInfo object for file to load /// @param isManifest whether to load a theme manifest or a qss file @@ -176,23 +62,22 @@ CustomTheme::CustomTheme(ITheme* baseTheme, QFileInfo& fileInfo, bool isManifest auto themeFilePath = FS::PathCombine(path, themeFile); - bool jsonDataIncomplete = false; - m_palette = baseTheme->colorScheme(); - if (readThemeJson(themeFilePath, m_palette, m_fadeAmount, m_fadeColor, m_name, m_widgets, m_qssFilePath, jsonDataIncomplete)) { + + bool hasCustomLogColors = false; + + if (read(themeFilePath, hasCustomLogColors)) { // If theme data was found, fade "Disabled" color of each role according to FadeAmount m_palette = fadeInactive(m_palette, m_fadeAmount, m_fadeColor); + + if (!hasCustomLogColors) + m_logColors = defaultLogColors(m_palette); } else { themeDebugLog() << "Did not read theme json file correctly, not changing theme, keeping previous."; + m_logColors = defaultLogColors(m_palette); return; } - // FIXME: This is kinda jank, it only actually checks if the qss file path is not present. It should actually check for any relevant - // missing data (e.g. name, colors) - if (jsonDataIncomplete) { - writeThemeJson(fileInfo.absoluteFilePath(), m_palette, m_fadeAmount, m_fadeColor, m_name, m_widgets, m_qssFilePath); - } - auto qssFilePath = FS::PathCombine(path, m_qssFilePath); QFileInfo info(qssFilePath); if (info.isFile()) { @@ -251,11 +136,6 @@ QString CustomTheme::name() return m_name; } -bool CustomTheme::hasColorScheme() -{ - return true; -} - QPalette CustomTheme::colorScheme() { return m_palette; @@ -289,3 +169,99 @@ QString CustomTheme::tooltip() { return m_tooltip; } + +bool CustomTheme::read(const QString& path, bool& hasCustomLogColors) +{ + QFileInfo pathInfo(path); + if (pathInfo.exists() && pathInfo.isFile()) { + try { + auto doc = Json::requireDocument(path, "Theme JSON file"); + const QJsonObject root = doc.object(); + m_name = Json::requireString(root, "name", "Theme name"); + m_widgets = Json::requireString(root, "widgets", "Qt widget theme"); + m_qssFilePath = Json::ensureString(root, "qssFilePath", "themeStyle.css"); + + auto readColor = [&](const QJsonObject& colors, const QString& colorName) -> QColor { + auto colorValue = Json::ensureString(colors, colorName, QString()); + if (!colorValue.isEmpty()) { + QColor color(colorValue); + if (!color.isValid()) { + themeWarningLog() << "Color value" << colorValue << "for" << colorName << "was not recognized."; + return {}; + } + return color; + } + return {}; + }; + + if (root.contains("colors")) { + auto colorsRoot = Json::requireObject(root, "colors"); + auto readAndSetPaletteColor = [&](QPalette::ColorRole role, const QString& colorName) { + auto color = readColor(colorsRoot, colorName); + if (color.isValid()) { + m_palette.setColor(role, color); + } else { + themeDebugLog() << "Color value for" << colorName << "was not present."; + } + }; + + // palette + readAndSetPaletteColor(QPalette::Window, "Window"); + readAndSetPaletteColor(QPalette::WindowText, "WindowText"); + readAndSetPaletteColor(QPalette::Base, "Base"); + readAndSetPaletteColor(QPalette::AlternateBase, "AlternateBase"); + readAndSetPaletteColor(QPalette::ToolTipBase, "ToolTipBase"); + readAndSetPaletteColor(QPalette::ToolTipText, "ToolTipText"); + readAndSetPaletteColor(QPalette::Text, "Text"); + readAndSetPaletteColor(QPalette::Button, "Button"); + readAndSetPaletteColor(QPalette::ButtonText, "ButtonText"); + readAndSetPaletteColor(QPalette::BrightText, "BrightText"); + readAndSetPaletteColor(QPalette::Link, "Link"); + readAndSetPaletteColor(QPalette::Highlight, "Highlight"); + readAndSetPaletteColor(QPalette::HighlightedText, "HighlightedText"); + + // fade + m_fadeColor = readColor(colorsRoot, "fadeColor"); + m_fadeAmount = Json::ensureDouble(colorsRoot, "fadeAmount", 0.5, "fade amount"); + } + + if (root.contains("logColors")) { + hasCustomLogColors = true; + + auto logColorsRoot = Json::requireObject(root, "logColors"); + auto readAndSetLogColor = [&](MessageLevel::Enum level, bool fg, const QString& colorName) { + auto color = readColor(logColorsRoot, colorName); + if (color.isValid()) { + if (fg) + m_logColors.foreground[level] = color; + else + m_logColors.background[level] = color; + } else { + themeDebugLog() << "Color value for" << colorName << "was not present."; + } + }; + + readAndSetLogColor(MessageLevel::Message, false, "MessageHighlight"); + readAndSetLogColor(MessageLevel::Launcher, false, "LauncherHighlight"); + readAndSetLogColor(MessageLevel::Debug, false, "DebugHighlight"); + readAndSetLogColor(MessageLevel::Warning, false, "WarningHighlight"); + readAndSetLogColor(MessageLevel::Error, false, "ErrorHighlight"); + readAndSetLogColor(MessageLevel::Fatal, false, "FatalHighlight"); + + readAndSetLogColor(MessageLevel::Message, true, "Message"); + readAndSetLogColor(MessageLevel::Launcher, true, "Launcher"); + readAndSetLogColor(MessageLevel::Debug, true, "Debug"); + readAndSetLogColor(MessageLevel::Warning, true, "Warning"); + readAndSetLogColor(MessageLevel::Error, true, "Error"); + readAndSetLogColor(MessageLevel::Fatal, true, "Fatal"); + } + } catch (const Exception& e) { + themeWarningLog() << "Couldn't load theme json: " << e.cause(); + return false; + } + } else { + themeDebugLog() << "No theme json present."; + return false; + } + return true; +} diff --git a/launcher/ui/themes/CustomTheme.h b/launcher/ui/themes/CustomTheme.h index 761a2bd90..b8d073921 100644 --- a/launcher/ui/themes/CustomTheme.h +++ b/launcher/ui/themes/CustomTheme.h @@ -2,6 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2024 Tayou + * Copyright (C) 2024 TheKodeToad * * 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 @@ -47,14 +48,16 @@ class CustomTheme : public ITheme { QString tooltip() override; bool hasStyleSheet() override; QString appStyleSheet() override; - bool hasColorScheme() override; QPalette colorScheme() override; double fadeAmount() override; QColor fadeColor() override; QString qtTheme() override; + LogColors logColorScheme() override { return m_logColors; } QStringList searchPaths() override; - private: /* data */ + private: + bool read(const QString& path, bool& hasCustomLogColors); + QPalette m_palette; QColor m_fadeColor; double m_fadeAmount; @@ -63,6 +66,7 @@ class CustomTheme : public ITheme { QString m_id; QString m_widgets; QString m_qssFilePath; + LogColors m_logColors; /** * The tooltip could be defined in the theme json, * or composed of other fields that could be in there. diff --git a/launcher/ui/themes/DarkTheme.cpp b/launcher/ui/themes/DarkTheme.cpp index 429d046ac..804126547 100644 --- a/launcher/ui/themes/DarkTheme.cpp +++ b/launcher/ui/themes/DarkTheme.cpp @@ -2,6 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2024 Tayou + * Copyright (C) 2024 TheKodeToad * * 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 @@ -46,11 +47,6 @@ QString DarkTheme::name() return QObject::tr("Dark"); } -bool DarkTheme::hasColorScheme() -{ - return true; -} - QPalette DarkTheme::colorScheme() { QPalette darkPalette; @@ -90,6 +86,7 @@ QString DarkTheme::appStyleSheet() { return "QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }"; } + QString DarkTheme::tooltip() { return ""; diff --git a/launcher/ui/themes/DarkTheme.h b/launcher/ui/themes/DarkTheme.h index 819f6a934..c97edbcbe 100644 --- a/launcher/ui/themes/DarkTheme.h +++ b/launcher/ui/themes/DarkTheme.h @@ -45,7 +45,6 @@ class DarkTheme : public FusionTheme { QString tooltip() override; bool hasStyleSheet() override; QString appStyleSheet() override; - bool hasColorScheme() override; QPalette colorScheme() override; double fadeAmount() override; QColor fadeColor() override; diff --git a/launcher/ui/themes/ITheme.cpp b/launcher/ui/themes/ITheme.cpp index 046ae16b4..cae6e90db 100644 --- a/launcher/ui/themes/ITheme.cpp +++ b/launcher/ui/themes/ITheme.cpp @@ -44,9 +44,7 @@ void ITheme::apply(bool) { APPLICATION->setStyleSheet(QString()); QApplication::setStyle(new HintOverrideProxyStyle(QStyleFactory::create(qtTheme()))); - if (hasColorScheme()) { - QApplication::setPalette(colorScheme()); - } + QApplication::setPalette(colorScheme()); APPLICATION->setStyleSheet(appStyleSheet()); QDir::setSearchPaths("theme", searchPaths()); } @@ -73,3 +71,30 @@ QPalette ITheme::fadeInactive(QPalette in, qreal bias, QColor color) blend(QPalette::HighlightedText); return in; } + +LogColors ITheme::defaultLogColors(const QPalette& palette) +{ + LogColors result; + + const QColor& bg = palette.color(QPalette::Base); + const QColor& fg = palette.color(QPalette::Text); + + auto blend = [bg, fg](QColor color) { + if (Rainbow::luma(fg) > Rainbow::luma(bg)) { + // for dark color schemes, produce a fitting color first + color = Rainbow::tint(fg, color, 0.5); + } + // adapt contrast + return Rainbow::mix(fg, color, 1); + }; + + result.background[MessageLevel::Fatal] = Qt::black; + + result.foreground[MessageLevel::Launcher] = blend(QColor("purple")); + result.foreground[MessageLevel::Debug] = blend(QColor("green")); + result.foreground[MessageLevel::Warning] = blend(QColor("orange")); + result.foreground[MessageLevel::Error] = blend(QColor("red")); + result.foreground[MessageLevel::Fatal] = blend(QColor("red")); + + return result; +} diff --git a/launcher/ui/themes/ITheme.h b/launcher/ui/themes/ITheme.h index 45d3e2739..7dc5fc64a 100644 --- a/launcher/ui/themes/ITheme.h +++ b/launcher/ui/themes/ITheme.h @@ -2,6 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Tayou + * Copyright (C) 2024 TheKodeToad * * 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 @@ -33,11 +34,19 @@ * limitations under the License. */ #pragma once +#include +#include #include #include class QStyle; +struct LogColors { + QMap background; + QMap foreground; +}; + +// TODO: rename to Theme; this is not an interface as it contains method implementations class ITheme { public: virtual ~ITheme() {} @@ -48,11 +57,12 @@ class ITheme { virtual bool hasStyleSheet() = 0; virtual QString appStyleSheet() = 0; virtual QString qtTheme() = 0; - virtual bool hasColorScheme() = 0; virtual QPalette colorScheme() = 0; virtual QColor fadeColor() = 0; virtual double fadeAmount() = 0; + virtual LogColors logColorScheme() { return defaultLogColors(colorScheme()); } virtual QStringList searchPaths() { return {}; } static QPalette fadeInactive(QPalette in, qreal bias, QColor color); + static LogColors defaultLogColors(const QPalette& palette); }; diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index 70de21894..791df2ed4 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -125,8 +125,3 @@ bool SystemTheme::hasStyleSheet() { return false; } - -bool SystemTheme::hasColorScheme() -{ - return true; -} diff --git a/launcher/ui/themes/SystemTheme.h b/launcher/ui/themes/SystemTheme.h index 5c58856cb..783f2e4c2 100644 --- a/launcher/ui/themes/SystemTheme.h +++ b/launcher/ui/themes/SystemTheme.h @@ -48,7 +48,6 @@ class SystemTheme : public ITheme { QString qtTheme() override; bool hasStyleSheet() override; QString appStyleSheet() override; - bool hasColorScheme() override; QPalette colorScheme() override; double fadeAmount() override; QColor fadeColor() override; diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index d57e166f4..ad9a6f88e 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -123,11 +123,11 @@ void ThemeManager::initializeWidgets() { themeDebugLog() << "Determining System Widget Theme..."; const auto& style = QApplication::style(); - currentlySelectedSystemTheme = style->objectName(); - themeDebugLog() << "System theme seems to be:" << currentlySelectedSystemTheme; + m_currentlySelectedSystemTheme = style->objectName(); + themeDebugLog() << "System theme seems to be:" << m_currentlySelectedSystemTheme; themeDebugLog() << "<> Initializing Widget Themes"; - themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique(currentlySelectedSystemTheme, true)); + themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique(m_currentlySelectedSystemTheme, true)); auto darkThemeId = addTheme(std::make_unique()); themeDebugLog() << "Loading Built-in Theme:" << darkThemeId; themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); @@ -196,8 +196,8 @@ QList ThemeManager::getValidApplicationThemes() QList ThemeManager::getValidCatPacks() { QList ret; - ret.reserve(m_cat_packs.size()); - for (auto&& [id, theme] : m_cat_packs) { + ret.reserve(m_catPacks.size()); + for (auto&& [id, theme] : m_catPacks) { ret.append(theme.get()); } return ret; @@ -246,6 +246,8 @@ void ThemeManager::setApplicationTheme(const QString& name, bool initial) auto& theme = themeIter->second; themeDebugLog() << "applying theme" << theme->name(); theme->apply(initial); + + m_logColors = theme->logColorScheme(); } else { themeWarningLog() << "Tried to set invalid theme:" << name; } @@ -258,7 +260,7 @@ void ThemeManager::applyCurrentlySelectedTheme(bool initial) themeDebugLog() << "<> Icon theme set."; auto applicationTheme = settings->get("ApplicationTheme").toString(); if (applicationTheme == "") { - applicationTheme = currentlySelectedSystemTheme; + applicationTheme = m_currentlySelectedSystemTheme; } setApplicationTheme(applicationTheme, initial); themeDebugLog() << "<> Application theme set."; @@ -266,8 +268,8 @@ void ThemeManager::applyCurrentlySelectedTheme(bool initial) QString ThemeManager::getCatPack(QString catName) { - auto catIter = m_cat_packs.find(!catName.isEmpty() ? catName : APPLICATION->settings()->get("BackgroundCat").toString()); - if (catIter != m_cat_packs.end()) { + auto catIter = m_catPacks.find(!catName.isEmpty() ? catName : APPLICATION->settings()->get("BackgroundCat").toString()); + if (catIter != m_catPacks.end()) { auto& catPack = catIter->second; themeDebugLog() << "applying catpack" << catPack->id(); return catPack->path(); @@ -275,14 +277,14 @@ QString ThemeManager::getCatPack(QString catName) themeWarningLog() << "Tried to get invalid catPack:" << catName; } - return m_cat_packs.begin()->second->path(); + return m_catPacks.begin()->second->path(); } QString ThemeManager::addCatPack(std::unique_ptr catPack) { QString id = catPack->id(); - if (m_cat_packs.find(id) == m_cat_packs.end()) - m_cat_packs.emplace(id, std::move(catPack)); + if (m_catPacks.find(id) == m_catPacks.end()) + m_catPacks.emplace(id, std::move(catPack)); else themeWarningLog() << "CatPack(" << id << ") not added to prevent id duplication"; return id; @@ -340,8 +342,8 @@ void ThemeManager::refresh() { m_themes.clear(); m_icons.clear(); - m_cat_packs.clear(); + m_catPacks.clear(); initializeThemes(); initializeCatPacks(); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 9d01d38e7..8bbcd34a9 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2024 Tayou - * Copyright (C) 2023 TheKodeToad + * Copyright (C) 2024 TheKodeToad * * 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 @@ -55,6 +55,8 @@ class ThemeManager { QString getCatPack(QString catName = ""); QList getValidCatPacks(); + const LogColors& getLogColors() { return m_logColors; } + void refresh(); private: @@ -63,8 +65,9 @@ class ThemeManager { QDir m_iconThemeFolder{ "iconthemes" }; QDir m_applicationThemeFolder{ "themes" }; QDir m_catPacksFolder{ "catpacks" }; - std::map> m_cat_packs; - QString currentlySelectedSystemTheme; + std::map> m_catPacks; + QString m_currentlySelectedSystemTheme; + LogColors m_logColors; void initializeThemes(); void initializeCatPacks(); From aa3a4585ee8663250636427f67afccb537ce4428 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Aug 2024 18:58:04 +0300 Subject: [PATCH 116/120] Add icons Signed-off-by: Trial97 --- launcher/resources/multimc/multimc.qrc | 6 + .../resources/multimc/scalable/adoptium.svg | 184 ++++++++++++++++++ launcher/resources/multimc/scalable/azul.svg | 17 ++ .../resources/multimc/scalable/mojang.svg | 55 ++++++ launcher/ui/java/InstallJavaDialog.cpp | 6 +- 5 files changed, 265 insertions(+), 3 deletions(-) create mode 100644 launcher/resources/multimc/scalable/adoptium.svg create mode 100644 launcher/resources/multimc/scalable/azul.svg create mode 100644 launcher/resources/multimc/scalable/mojang.svg diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index eeba32186..25edd09e0 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -353,5 +353,11 @@ scalable/instances/neoforged.svg 128x128/instances/forge.png 128x128/instances/liteloader.png + + + scalable/adoptium.svg + scalable/azul.svg + scalable/mojang.svg + diff --git a/launcher/resources/multimc/scalable/adoptium.svg b/launcher/resources/multimc/scalable/adoptium.svg new file mode 100644 index 000000000..3fcc956ed --- /dev/null +++ b/launcher/resources/multimc/scalable/adoptium.svg @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/launcher/resources/multimc/scalable/azul.svg b/launcher/resources/multimc/scalable/azul.svg new file mode 100644 index 000000000..1c4356eb7 --- /dev/null +++ b/launcher/resources/multimc/scalable/azul.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/launcher/resources/multimc/scalable/mojang.svg b/launcher/resources/multimc/scalable/mojang.svg new file mode 100644 index 000000000..0c1f48d3d --- /dev/null +++ b/launcher/resources/multimc/scalable/mojang.svg @@ -0,0 +1,55 @@ + + Created with Fabric.js 3.6.3 diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index 01ec56dfd..decbfb77d 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -273,11 +273,11 @@ QList InstallDialog::getPages() { return { // Mojang - new InstallJavaPage("net.minecraft.java", "", tr("Mojang")), + new InstallJavaPage("net.minecraft.java", "mojang", tr("Mojang")), // Adoptium - new InstallJavaPage("net.adoptium.java", "", tr("Adoptium")), + new InstallJavaPage("net.adoptium.java", "adoptium", tr("Adoptium")), // Azul - new InstallJavaPage("com.azul.java", "", tr("Azul")), + new InstallJavaPage("com.azul.java", "azul", tr("Azul Zulu")), }; } From 7d9e47ac18fc2b3278027bb99c9b5686aa165dc7 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Aug 2024 18:58:38 +0300 Subject: [PATCH 117/120] Change major java column name Signed-off-by: Trial97 --- launcher/VersionProxyModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 62cf4c221..552900d35 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -121,7 +121,7 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, case JavaName: return tr("Java Name"); case JavaMajor: - return tr("Major"); + return tr("Major Version"); case Time: return tr("Released"); } From 0b05c7cb07030bada88ac253e9a92c24ea4bd473 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Aug 2024 18:59:09 +0300 Subject: [PATCH 118/120] fix bug with buton not updating corectly for java dialog Signed-off-by: Trial97 --- launcher/ui/java/InstallJavaDialog.cpp | 11 +++++------ launcher/ui/java/InstallJavaDialog.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/launcher/ui/java/InstallJavaDialog.cpp b/launcher/ui/java/InstallJavaDialog.cpp index decbfb77d..4fb9fc2d2 100644 --- a/launcher/ui/java/InstallJavaDialog.cpp +++ b/launcher/ui/java/InstallJavaDialog.cpp @@ -259,14 +259,14 @@ InstallDialog::InstallDialog(const QString& uid, BaseInstance* instance, QWidget auto cast = pageCast(page); cast->setRecomend(true); - connect(cast, &InstallJavaPage::selectionChanged, this, [this] { validate(); }); + connect(cast, &InstallJavaPage::selectionChanged, this, [this, cast] { validate(cast); }); if (!recommendedJavas.isEmpty()) { cast->setRecommendedMajors(recommendedJavas); } } - connect(container, &PageContainer::selectedPageChanged, this, [this] { validate(); }); + connect(container, &PageContainer::selectedPageChanged, this, [this](BasePage* previous, BasePage* selected) { validate(selected); }); pageCast(container->selectedPage())->selectSearch(); - validate(); + validate(container->selectedPage()); } QList InstallDialog::getPages() @@ -286,10 +286,9 @@ QString InstallDialog::dialogTitle() return tr("Install Java"); } -void InstallDialog::validate() +void InstallDialog::validate(BasePage* selected) { - buttons->button(QDialogButtonBox::Ok) - ->setEnabled(!!std::dynamic_pointer_cast(pageCast(container->selectedPage())->selectedVersion())); + buttons->button(QDialogButtonBox::Ok)->setEnabled(!!std::dynamic_pointer_cast(pageCast(selected)->selectedVersion())); } void InstallDialog::done(int result) diff --git a/launcher/ui/java/InstallJavaDialog.h b/launcher/ui/java/InstallJavaDialog.h index d6f879207..7d0edbfdd 100644 --- a/launcher/ui/java/InstallJavaDialog.h +++ b/launcher/ui/java/InstallJavaDialog.h @@ -37,7 +37,7 @@ class InstallDialog final : public QDialog, private BasePageProvider { QList getPages() override; QString dialogTitle() override; - void validate(); + void validate(BasePage* selected); void done(int result) override; private: From 5f64d7dc47b78a9fdd62b3f54ecb6bb1361b9e9b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Aug 2024 20:38:08 +0300 Subject: [PATCH 119/120] update adoptium icon Signed-off-by: Trial97 --- .../resources/multimc/scalable/adoptium.svg | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/launcher/resources/multimc/scalable/adoptium.svg b/launcher/resources/multimc/scalable/adoptium.svg index 3fcc956ed..d48f8b7d9 100644 --- a/launcher/resources/multimc/scalable/adoptium.svg +++ b/launcher/resources/multimc/scalable/adoptium.svg @@ -1,6 +1,6 @@ - + transform="matrix(13.679999,0,0,13.679976,-6760.5652,-16025.746)"> @@ -156,7 +152,7 @@ + transform="matrix(13.679999,0,0,13.679976,-6760.5652,-16025.746)"> @@ -168,7 +164,7 @@ + transform="matrix(1.2000009,0,0,1.1999989,-853.84911,665.71675)"> Date: Thu, 22 Aug 2024 19:07:15 +0100 Subject: [PATCH 120/120] Fix invalid Java path message Signed-off-by: TheKodeToad --- launcher/launch/steps/CheckJava.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/launcher/launch/steps/CheckJava.cpp b/launcher/launch/steps/CheckJava.cpp index 81337a88e..4628e154d 100644 --- a/launcher/launch/steps/CheckJava.cpp +++ b/launcher/launch/steps/CheckJava.cpp @@ -45,20 +45,23 @@ void CheckJava::executeTask() { auto instance = m_parent->instance(); auto settings = instance->settings(); - m_javaPath = FS::ResolveExecutable(settings->get("JavaPath").toString()); + + QString javaPathSetting = settings->get("JavaPath").toString(); + m_javaPath = FS::ResolveExecutable(javaPathSetting); + bool perInstance = settings->get("OverrideJava").toBool() || settings->get("OverrideJavaLocation").toBool(); auto realJavaPath = QStandardPaths::findExecutable(m_javaPath); if (realJavaPath.isEmpty()) { if (perInstance) { - emit logLine(QString("The java binary \"%1\" couldn't be found. Please fix the java path " + emit logLine(QString("The Java binary \"%1\" couldn't be found. Please fix the Java path " "override in the instance's settings or disable it.") - .arg(m_javaPath), + .arg(javaPathSetting), MessageLevel::Warning); } else { - emit logLine(QString("The java binary \"%1\" couldn't be found. Please set up java in " + emit logLine(QString("The Java binary \"%1\" couldn't be found. Please set up Java in " "the settings.") - .arg(m_javaPath), + .arg(javaPathSetting), MessageLevel::Warning); } emitFailed(QString("Java path is not valid."));