From 81282bf7e0189ede29d2db14f85ef2c886d8b583 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 26 Jan 2024 00:22:05 +0200 Subject: [PATCH] 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(); + } }