From 6f7624a66d82637c35dce999c3c5efbf390e0a94 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Fri, 31 Dec 2021 21:12:51 +0000 Subject: [PATCH 01/45] Add embedded logging configs Minecraft's default logging configs output XML to stdout, because the modern launcher parses it to provide a "nicer" console. We don't do that, so this commit adds embedded versions of the logging configs which just output log lines normally. --- .../skcraft/launcher/update/BaseUpdater.java | 17 +++++++++++-- .../skcraft/launcher/logging/client-1.12.xml | 24 ++++++++++++++++++ .../skcraft/launcher/logging/client-1.7.xml | 25 +++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 launcher/src/main/resources/com/skcraft/launcher/logging/client-1.12.xml create mode 100644 launcher/src/main/resources/com/skcraft/launcher/logging/client-1.7.xml diff --git a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java index fac401dad..15dfd48bc 100644 --- a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java +++ b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java @@ -34,8 +34,11 @@ import javax.swing.*; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; import java.util.logging.Level; @@ -274,18 +277,28 @@ protected void installLibraries(@NonNull Installer installer, } } - // Fetch logging config + // Use our custom logging config depending on what the manifest specifies if (versionManifest.getLogging() != null) { VersionManifest.LoggingConfig config = versionManifest.getLogging().getClient(); VersionManifest.Artifact file = config.getFile(); File targetFile = new File(librariesDir, file.getId()); + InputStream embeddedConfig = Launcher.class.getResourceAsStream("logging/" + file.getId()); - if (!targetFile.exists() || !Objects.equals(config.getFile().getHash(), FileUtils.getShaHash(targetFile))) { + if (embeddedConfig == null) { + // No embedded config, just use whatever the server gives us File tempFile = installer.getDownloader().download(url(file.getUrl()), file.getHash(), file.getSize(), file.getId()); log.info("Downloading logging config " + file.getId() + " from " + file.getUrl()); installer.queue(new FileMover(tempFile, targetFile)); + } else if (!targetFile.exists() || FileUtils.getShaHash(targetFile).equals(file.getHash())) { + // Use our embedded replacement + + Path tempFile = installer.getTempDir().toPath().resolve(file.getId()); + Files.copy(embeddedConfig, tempFile); + + log.info("Substituting embedded logging config " + file.getId()); + installer.queue(new FileMover(tempFile.toFile(), targetFile)); } } } diff --git a/launcher/src/main/resources/com/skcraft/launcher/logging/client-1.12.xml b/launcher/src/main/resources/com/skcraft/launcher/logging/client-1.12.xml new file mode 100644 index 000000000..2e9ac98e5 --- /dev/null +++ b/launcher/src/main/resources/com/skcraft/launcher/logging/client-1.12.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/launcher/src/main/resources/com/skcraft/launcher/logging/client-1.7.xml b/launcher/src/main/resources/com/skcraft/launcher/logging/client-1.7.xml new file mode 100644 index 000000000..87f3dea8e --- /dev/null +++ b/launcher/src/main/resources/com/skcraft/launcher/logging/client-1.7.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From 725f747f63eb83638ff4940df347582d6023640d Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Fri, 31 Dec 2021 22:20:16 +0000 Subject: [PATCH 02/45] Ensure installer temporary directory exists when installing --- .../src/main/java/com/skcraft/launcher/update/BaseUpdater.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java index 15dfd48bc..4f35b0de6 100644 --- a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java +++ b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java @@ -82,6 +82,9 @@ protected Manifest installPackage(@NonNull Installer installer, @NonNull Instanc final File cachePath = new File(instance.getDir(), "update_cache.json"); final File featuresPath = new File(instance.getDir(), "features.json"); + // Make sure the temp dir exists + installer.getTempDir().mkdirs(); + final InstallLog previousLog = Persistence.read(logPath, InstallLog.class); final InstallLog currentLog = new InstallLog(); currentLog.setBaseDir(contentDir); From 28017e8103dc183ecea8031c71aef94b47472457 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Sat, 1 Jan 2022 04:34:15 +0000 Subject: [PATCH 03/45] Fix edge case in logging config handling If the user cancelled the install process after the temp logging config file was created, but before the installer executes, the pack would fail to install on relaunch. Fix by allowing overwriting of the temp file. --- .../src/main/java/com/skcraft/launcher/update/BaseUpdater.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java index 4f35b0de6..e447ef031 100644 --- a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java +++ b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java @@ -39,6 +39,7 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.util.*; import java.util.logging.Level; @@ -298,7 +299,7 @@ protected void installLibraries(@NonNull Installer installer, // Use our embedded replacement Path tempFile = installer.getTempDir().toPath().resolve(file.getId()); - Files.copy(embeddedConfig, tempFile); + Files.copy(embeddedConfig, tempFile, StandardCopyOption.REPLACE_EXISTING); log.info("Substituting embedded logging config " + file.getId()); installer.queue(new FileMover(tempFile.toFile(), targetFile)); From 291f62a4dcf6686696fb01de8133a355ca5172d2 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Tue, 4 Jan 2022 00:41:53 +0000 Subject: [PATCH 04/45] Allow Microsoft authentication to use xdg-open on Linux --- .../microsoft/MicrosoftWebAuthorizer.java | 3 ++- .../skcraft/launcher/swing/SwingHelper.java | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/MicrosoftWebAuthorizer.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/MicrosoftWebAuthorizer.java index eb07245b9..a4d79535c 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/MicrosoftWebAuthorizer.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/MicrosoftWebAuthorizer.java @@ -1,6 +1,7 @@ package com.skcraft.launcher.auth.microsoft; import com.skcraft.launcher.auth.AuthenticationException; +import com.skcraft.launcher.swing.SwingHelper; import com.skcraft.launcher.util.HttpRequest; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -30,7 +31,7 @@ public OauthResult authorize() throws IOException, AuthenticationException, Inte private OauthResult authorizeInteractive() throws IOException, AuthenticationException, InterruptedException { OauthHttpHandler httpHandler = new OauthHttpHandler(); - Desktop.getDesktop().browse(generateInteractiveUrl(httpHandler.getPort())); + SwingHelper.openURL(generateInteractiveUrl(httpHandler.getPort())); return httpHandler.await(); } diff --git a/launcher/src/main/java/com/skcraft/launcher/swing/SwingHelper.java b/launcher/src/main/java/com/skcraft/launcher/swing/SwingHelper.java index 8024e0b2f..b8239dfe3 100644 --- a/launcher/src/main/java/com/skcraft/launcher/swing/SwingHelper.java +++ b/launcher/src/main/java/com/skcraft/launcher/swing/SwingHelper.java @@ -35,6 +35,7 @@ import java.io.*; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.List; @@ -104,16 +105,7 @@ public static void openURL(@NonNull String url, @NonNull Component parentCompone */ public static void openURL(URL url, Component parentComponent) { try { - Desktop.getDesktop().browse(url.toURI()); - } catch (UnsupportedOperationException e) { - if (Environment.detectPlatform() == Platform.LINUX) { - // Try xdg-open instead - try { - Runtime.getRuntime().exec(new String[]{"xdg-open", url.toString()}); - } catch (IOException ex) { - showErrorDialog(parentComponent, tr("errors.openUrlError", url.toString()), tr("errorTitle"), ex); - } - } + openURL(url.toURI()); } catch (IOException e) { showErrorDialog(parentComponent, tr("errors.openUrlError", url.toString()), SharedLocale.tr("errorTitle")); } catch (URISyntaxException e) { @@ -121,6 +113,17 @@ public static void openURL(URL url, Component parentComponent) { } } + public static void openURL(URI url) throws IOException { + try { + Desktop.getDesktop().browse(url); + } catch (UnsupportedOperationException e) { + if (Environment.detectPlatform() == Platform.LINUX) { + // Try xdg-open instead + Runtime.getRuntime().exec(new String[]{"xdg-open", url.toString()}); + } + } + } + /** * Shows an popup error dialog, with potential extra details shown either immediately * or available on the dialog. From 288da94249d899fad4fa9cba83f5ce589379268b Mon Sep 17 00:00:00 2001 From: Magi1053 Date: Sat, 22 Jan 2022 19:37:10 -0600 Subject: [PATCH 05/45] Fix pastebin uploader --- .../src/main/java/com/skcraft/launcher/util/PastebinPoster.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/util/PastebinPoster.java b/launcher/src/main/java/com/skcraft/launcher/util/PastebinPoster.java index 53a966682..285c595cf 100644 --- a/launcher/src/main/java/com/skcraft/launcher/util/PastebinPoster.java +++ b/launcher/src/main/java/com/skcraft/launcher/util/PastebinPoster.java @@ -42,7 +42,7 @@ public void run() { InputStream in = null; try { - URL url = new URL("http://pastebin.com/api/api_post.php"); + URL url = new URL("https://pastebin.com/api/api_post.php"); conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(CONNECT_TIMEOUT); conn.setReadTimeout(READ_TIMEOUT); From 53ba054c2c3ac3717b4b177693c30b1935b6868b Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Mon, 18 Apr 2022 19:21:20 +0100 Subject: [PATCH 06/45] Change Java runtime selector to show "unknown" instead of "null" --- .../java/com/skcraft/launcher/launch/runtime/JavaRuntime.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntime.java b/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntime.java index 7d92730bd..ed0e39f93 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntime.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntime.java @@ -108,6 +108,8 @@ public int compareTo(JavaRuntime o) { @Override public String toString() { + String version = this.version != null ? this.version : "unknown"; + return String.format("Java %s (%s) (%s)", version, is64Bit ? "64-bit" : "32-bit", dir); } } From bad4363bed60a6486aacd49d87342486e86751c3 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Mon, 18 Apr 2022 22:37:48 +0100 Subject: [PATCH 07/45] Remove broken skin fetching for Yggdrasil auth "mandatory migration" my ass --- .../skcraft/launcher/auth/YggdrasilLoginService.java | 11 +++-------- .../auth/microsoft/MinecraftServicesAuthorizer.java | 8 +++++++- .../skcraft/launcher/dialog/AccountSelectDialog.java | 3 ++- .../com/skcraft/launcher/lang/Launcher.properties | 1 + 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/YggdrasilLoginService.java b/launcher/src/main/java/com/skcraft/launcher/auth/YggdrasilLoginService.java index 1e7993425..0ea50c12f 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/YggdrasilLoginService.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/YggdrasilLoginService.java @@ -7,9 +7,6 @@ package com.skcraft.launcher.auth; import com.fasterxml.jackson.annotation.*; -import com.skcraft.launcher.auth.microsoft.MinecraftServicesAuthorizer; -import com.skcraft.launcher.auth.microsoft.model.McProfileResponse; -import com.skcraft.launcher.auth.skin.MinecraftSkinService; import com.skcraft.launcher.util.HttpRequest; import lombok.Data; import lombok.RequiredArgsConstructor; @@ -63,13 +60,11 @@ private Session call(URL url, Object payload, SavedSession previous) if (previous != null && previous.getAvatarImage() != null) { profile.setAvatarImage(previous.getAvatarImage()); - } else { - McProfileResponse skinProfile = MinecraftServicesAuthorizer - .getUserProfile("Bearer " + response.getAccessToken()); - - profile.setAvatarImage(MinecraftSkinService.fetchSkinHead(skinProfile)); } + // DEPRECEATION: minecraft services API no longer accepts yggdrasil tokens + // login still works though. until it doesn't, this class will remain + return profile; } } diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/MinecraftServicesAuthorizer.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/MinecraftServicesAuthorizer.java index 528fbbf10..a64a67d4c 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/MinecraftServicesAuthorizer.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/MinecraftServicesAuthorizer.java @@ -37,7 +37,13 @@ public static McProfileResponse getUserProfile(String authorization) .header("Authorization", authorization) .execute() .expectResponseCodeOr(200, req -> { - McServicesError error = req.returnContent().asJson(McServicesError.class); + HttpRequest.BufferedResponse content = req.returnContent(); + if (content.asBytes().length == 0) { + return new AuthenticationException("Got empty response from Minecraft services", + SharedLocale.tr("login.minecraft.error", req.getResponseCode())); + } + + McServicesError error = content.asJson(McServicesError.class); if (error.getError().equals("NOT_FOUND")) { return new AuthenticationException("No Minecraft profile", diff --git a/launcher/src/main/java/com/skcraft/launcher/dialog/AccountSelectDialog.java b/launcher/src/main/java/com/skcraft/launcher/dialog/AccountSelectDialog.java index 9221d7942..6015f026e 100644 --- a/launcher/src/main/java/com/skcraft/launcher/dialog/AccountSelectDialog.java +++ b/launcher/src/main/java/com/skcraft/launcher/dialog/AccountSelectDialog.java @@ -184,7 +184,8 @@ public void onFailure(Throwable t) { if (t instanceof AuthenticationException) { if (((AuthenticationException) t).isInvalidatedSession()) { // Just need to log in again - LoginDialog.ReloginDetails details = new LoginDialog.ReloginDetails(session.getUsername(), t.getLocalizedMessage()); + LoginDialog.ReloginDetails details = new LoginDialog.ReloginDetails(session.getUsername(), + SharedLocale.tr("login.relogin", t.getLocalizedMessage())); Session newSession = LoginDialog.showLoginRequest(AccountSelectDialog.this, launcher, details); setResult(newSession); diff --git a/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties b/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties index d8699d433..652c77411 100644 --- a/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties +++ b/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties @@ -116,6 +116,7 @@ login.loggingInStatus=Logging in to Minecraft... login.noLoginError=Please enter your account details. login.noLoginTitle=Missing Account login.minecraftNotOwnedError=Sorry, Minecraft is not owned on that account. +login.relogin=Please log in again. ({0}) login.microsoft.seeBrowser=Check your browser to login with Microsoft. login.xbox.generic=Failed to authenticate with Xbox Live. From 79b1289aff274e5acc982ab99503978a8c77b65c Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Fri, 22 Apr 2022 00:47:49 +0100 Subject: [PATCH 08/45] Check for launcher updates when the game closes --- .../src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java b/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java index 2083da75b..664afcdf7 100644 --- a/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java +++ b/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java @@ -395,6 +395,7 @@ public void gameStarted() { @Override public void gameClosed() { launcher.showLauncherWindow(); + launcher.getUpdateManager().checkForUpdate(); } } From 3c4c38ea84016bf4c831e6bf26bb1c1c39d74216 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Fri, 22 Apr 2022 01:10:06 +0100 Subject: [PATCH 09/45] Improve Java runtime finder resiliency Found some more edge cases in the wild - though to be honest this entire thing is edge cases. Sometimes /release exists, but the actual binaries are in /jre/bin; this commit changes behaviour to look for the two things independently. --- .../launch/runtime/JavaRuntimeFinder.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntimeFinder.java b/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntimeFinder.java index 7af48c84a..456a07577 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntimeFinder.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntimeFinder.java @@ -73,6 +73,7 @@ public static JavaRuntime getRuntimeFromPath(String path) { } public static JavaRuntime getRuntimeFromPath(File target) { + // Normalize target to root first if (target.isFile()) { // Probably referring directly to bin/java, back up two levels target = target.getParentFile().getParentFile(); @@ -81,20 +82,26 @@ public static JavaRuntime getRuntimeFromPath(File target) { target = target.getParentFile(); } - { - File jre = new File(target, "jre/release"); - if (jre.isFile()) { - target = jre.getParentFile(); - } + // Find the release file + File releaseFile = new File(target, "release"); + if (!releaseFile.isFile()) { + releaseFile = new File(target, "jre/release"); + // may still not exist - parseFromRelease below will return null if so } - JavaReleaseFile release = JavaReleaseFile.parseFromRelease(target); + // Find the bin folder + File binFolder = new File(target, "bin"); + if (!binFolder.isDirectory()) { + binFolder = new File(target, "jre/bin"); + } + + JavaReleaseFile release = JavaReleaseFile.parseFromRelease(releaseFile.getParentFile()); if (release == null) { // Make some assumptions... - return new JavaRuntime(target, null, true); + return new JavaRuntime(binFolder.getParentFile(), null, true); } - return new JavaRuntime(target, release.getVersion(), release.isArch64Bit()); + return new JavaRuntime(binFolder.getParentFile(), release.getVersion(), release.isArch64Bit()); } private static PlatformRuntimeFinder getRuntimeFinder(Environment env) { From 8e1337d603c4c66501b0a7bb34e31c154e9c7d86 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Sat, 23 Apr 2022 19:49:04 +0100 Subject: [PATCH 10/45] Disregard Java runtimes that don't have a bin folder --- .../skcraft/launcher/launch/runtime/JavaRuntimeFinder.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntimeFinder.java b/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntimeFinder.java index 456a07577..01ecf2efe 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntimeFinder.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/runtime/JavaRuntimeFinder.java @@ -43,6 +43,7 @@ public static List getAvailableRuntimes() { // Add system Javas runtimeFinder.getCandidateJavaLocations().stream() .map(JavaRuntimeFinder::getRuntimeFromPath) + .filter(Objects::nonNull) .forEach(entries::add); // Add extra runtimes @@ -95,6 +96,11 @@ public static JavaRuntime getRuntimeFromPath(File target) { binFolder = new File(target, "jre/bin"); } + if (!binFolder.isDirectory()) { + // No bin folder, this isn't a usable install + return null; + } + JavaReleaseFile release = JavaReleaseFile.parseFromRelease(releaseFile.getParentFile()); if (release == null) { // Make some assumptions... From 54c05d1f9b5a3c1adf8ae8c35c59d8e6a0bfea89 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Tue, 26 Apr 2022 22:42:15 +0100 Subject: [PATCH 11/45] Upgrade to Gradle 7 --- build.gradle | 21 +++++------------- creator-tools/build.gradle | 16 ++++++++------ gradle/wrapper/gradle-wrapper.properties | 2 +- launcher-bootstrap/build.gradle | 12 ++++++---- launcher-builder/build.gradle | 15 ++++++++----- launcher-fancy/build.gradle | 12 ++++++---- launcher/build.gradle | 28 ++++++++++++++---------- 7 files changed, 59 insertions(+), 47 deletions(-) diff --git a/build.gradle b/build.gradle index ef0c52bca..19a1c131f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,16 +1,5 @@ -buildscript { - repositories { - mavenCentral() - jcenter() - } - - dependencies { - classpath "com.github.jengelman.gradle.plugins:shadow:2.0.1" - } -} - plugins { - id "com.github.johnrengelman.shadow" version "4.0.4" + id "com.github.johnrengelman.shadow" version "7.1.2" id 'io.freefair.lombok' version '5.3.0' } @@ -24,13 +13,15 @@ println """ subprojects { apply plugin: 'java' - apply plugin: 'maven' group = 'com.skcraft' version = '4.6-SNAPSHOT' - sourceCompatibility = 1.8 - targetCompatibility = 1.8 + java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + } + } repositories { mavenCentral() diff --git a/creator-tools/build.gradle b/creator-tools/build.gradle index 09dada89f..94aa5e712 100644 --- a/creator-tools/build.gradle +++ b/creator-tools/build.gradle @@ -5,15 +5,15 @@ plugins { } version = "2.1.0-SNAPSHOT" -sourceCompatibility = 1.8 -targetCompatibility = 1.8 -mainClassName = "com.skcraft.launcher.creator.Creator" +application { + mainClassName = "com.skcraft.launcher.creator.Creator" +} dependencies { - compile project(':launcher-builder') - compile 'org.eclipse.jetty:jetty-server:9.3.1.v20150714' - compile 'com.jidesoft:jide-oss:3.6.10' + implementation project(':launcher-builder') + implementation 'org.eclipse.jetty:jetty-server:9.3.1.v20150714' + implementation 'com.jidesoft:jide-oss:3.6.18' } processResources { @@ -27,4 +27,6 @@ processResources { shadowJar { } -build.dependsOn(shadowJar) +build { + dependsOn(shadowJar) +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index da9702f9e..aa991fcea 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/launcher-bootstrap/build.gradle b/launcher-bootstrap/build.gradle index 6400242fa..c165d7bad 100644 --- a/launcher-bootstrap/build.gradle +++ b/launcher-bootstrap/build.gradle @@ -4,11 +4,13 @@ plugins { id 'io.freefair.lombok' } -mainClassName = "com.skcraft.launcher.Bootstrap" +application { + mainClassName = "com.skcraft.launcher.Bootstrap" +} dependencies { - compile 'com.googlecode.json-simple:json-simple:1.1.1' - compile 'javax.xml.bind:jaxb-api:2.3.0' + implementation 'com.googlecode.json-simple:json-simple:1.1.1' + implementation 'javax.xml.bind:jaxb-api:2.3.0' } processResources { @@ -22,4 +24,6 @@ processResources { shadowJar { } -build.dependsOn(shadowJar) +build { + dependsOn(shadowJar) +} diff --git a/launcher-builder/build.gradle b/launcher-builder/build.gradle index 0d8387c45..91ddff48a 100644 --- a/launcher-builder/build.gradle +++ b/launcher-builder/build.gradle @@ -1,18 +1,23 @@ plugins { id 'application' + id 'java-library' id "com.github.johnrengelman.shadow" id 'io.freefair.lombok' } -mainClassName = "com.skcraft.launcher.builder.PackageBuilder" +application { + mainClassName = "com.skcraft.launcher.builder.PackageBuilder" +} dependencies { - compile project(':launcher') - compile 'org.tukaani:xz:1.0' - compile 'org.apache.commons:commons-compress:1.9' + api project(':launcher') + implementation 'org.tukaani:xz:1.0' + implementation 'org.apache.commons:commons-compress:1.9' } shadowJar { } -build.dependsOn(shadowJar) +build { + dependsOn(shadowJar) +} diff --git a/launcher-fancy/build.gradle b/launcher-fancy/build.gradle index 6cc9891f1..bbd656125 100644 --- a/launcher-fancy/build.gradle +++ b/launcher-fancy/build.gradle @@ -4,7 +4,9 @@ plugins { id 'io.freefair.lombok' } -mainClassName = "com.skcraft.launcher.FancyLauncher" +application { + mainClassName = "com.skcraft.launcher.FancyLauncher" +} repositories { maven { @@ -14,11 +16,13 @@ repositories { } dependencies { - compile project(':launcher') - compile 'io.github.cottonmc.insubstantial:substance:7.3.1-SNAPSHOT' + implementation project(':launcher') + implementation 'io.github.cottonmc.insubstantial:substance:7.3.1-SNAPSHOT' } shadowJar { } -build.dependsOn(shadowJar) +build { + dependsOn(shadowJar) +} diff --git a/launcher/build.gradle b/launcher/build.gradle index 1525face0..8d1cff443 100644 --- a/launcher/build.gradle +++ b/launcher/build.gradle @@ -1,21 +1,25 @@ plugins { id 'application' + id 'java-library' id "com.github.johnrengelman.shadow" id 'io.freefair.lombok' } -mainClassName = "com.skcraft.launcher.Launcher" +application { + mainClassName = "com.skcraft.launcher.Launcher" +} dependencies { - compile 'javax.xml.bind:jaxb-api:2.2.4' - compile 'com.fasterxml.jackson.core:jackson-databind:2.3.0' - compile 'commons-lang:commons-lang:2.6' - compile 'commons-io:commons-io:1.2' - compile 'com.google.guava:guava:15.0' - compile 'com.beust:jcommander:1.32' - compile 'com.miglayout:miglayout:3.7.4' - compile 'com.google.code.findbugs:jsr305:3.0.0' - compile 'com.googlecode.plist:dd-plist:1.23' + api 'javax.xml.bind:jaxb-api:2.2.4' + api 'com.fasterxml.jackson.core:jackson-databind:2.3.0' + api 'commons-lang:commons-lang:2.6' + api 'commons-io:commons-io:1.2' + api 'com.google.guava:guava:15.0' + api 'com.beust:jcommander:1.32' + api 'com.miglayout:miglayout:3.7.4' + api 'com.google.code.findbugs:jsr305:3.0.0' + + implementation 'com.googlecode.plist:dd-plist:1.23' implementation 'net.java.dev.jna:jna-platform:5.10.0' } @@ -31,4 +35,6 @@ processResources { shadowJar { } -build.dependsOn(shadowJar) +build { + dependsOn(shadowJar) +} From 868426498f725448cee80e45ed37879ac8396841 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Tue, 26 Apr 2022 23:02:58 +0100 Subject: [PATCH 12/45] Upgrade dependencies & fix deprecations --- launcher-bootstrap/build.gradle | 2 +- launcher-builder/build.gradle | 3 +-- .../com/skcraft/launcher/builder/PackageBuilder.java | 2 +- launcher/build.gradle | 11 +++++------ .../src/main/java/com/skcraft/launcher/Launcher.java | 2 +- .../skcraft/launcher/auth/MicrosoftLoginService.java | 4 ++-- .../launcher/auth/microsoft/model/McAuthResponse.java | 4 ++-- .../launcher/auth/microsoft/model/TokenResponse.java | 4 ++-- .../auth/microsoft/model/XblAuthProperties.java | 4 ++-- .../auth/microsoft/model/XboxAuthRequest.java | 4 ++-- .../auth/microsoft/model/XboxAuthResponse.java | 4 ++-- .../auth/microsoft/model/XstsAuthProperties.java | 4 ++-- .../launcher/auth/microsoft/model/XstsError.java | 4 ++-- .../minecraft/mapper/ArgumentValueDeserializer.java | 2 +- .../mapper/MinecraftArgumentsDeserializer.java | 2 +- .../com/skcraft/launcher/persistence/Persistence.java | 4 ++-- .../java/com/skcraft/launcher/util/HttpRequest.java | 2 +- 17 files changed, 30 insertions(+), 32 deletions(-) diff --git a/launcher-bootstrap/build.gradle b/launcher-bootstrap/build.gradle index c165d7bad..872063e26 100644 --- a/launcher-bootstrap/build.gradle +++ b/launcher-bootstrap/build.gradle @@ -10,7 +10,7 @@ application { dependencies { implementation 'com.googlecode.json-simple:json-simple:1.1.1' - implementation 'javax.xml.bind:jaxb-api:2.3.0' + implementation 'javax.xml.bind:jaxb-api:2.3.1' } processResources { diff --git a/launcher-builder/build.gradle b/launcher-builder/build.gradle index 91ddff48a..008cfa69e 100644 --- a/launcher-builder/build.gradle +++ b/launcher-builder/build.gradle @@ -11,8 +11,7 @@ application { dependencies { api project(':launcher') - implementation 'org.tukaani:xz:1.0' - implementation 'org.apache.commons:commons-compress:1.9' + implementation 'org.apache.commons:commons-compress:1.21' } shadowJar { diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java index 92f54fdf9..6b85f989a 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java @@ -367,7 +367,7 @@ public void writeManifest(@NonNull File path) throws IOException { private static BuilderOptions parseArgs(String[] args) { BuilderOptions options = new BuilderOptions(); - new JCommander(options, args); + new JCommander(options).parse(args); options.choosePaths(); return options; } diff --git a/launcher/build.gradle b/launcher/build.gradle index 8d1cff443..28c4bc651 100644 --- a/launcher/build.gradle +++ b/launcher/build.gradle @@ -10,18 +10,17 @@ application { } dependencies { - api 'javax.xml.bind:jaxb-api:2.2.4' - api 'com.fasterxml.jackson.core:jackson-databind:2.3.0' + api 'javax.xml.bind:jaxb-api:2.3.1' + api 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' api 'commons-lang:commons-lang:2.6' api 'commons-io:commons-io:1.2' api 'com.google.guava:guava:15.0' - api 'com.beust:jcommander:1.32' + api 'com.beust:jcommander:1.82' api 'com.miglayout:miglayout:3.7.4' - api 'com.google.code.findbugs:jsr305:3.0.0' + api 'com.google.code.findbugs:jsr305:3.0.2' implementation 'com.googlecode.plist:dd-plist:1.23' - - implementation 'net.java.dev.jna:jna-platform:5.10.0' + implementation 'net.java.dev.jna:jna-platform:5.11.0' } processResources { diff --git a/launcher/src/main/java/com/skcraft/launcher/Launcher.java b/launcher/src/main/java/com/skcraft/launcher/Launcher.java index b2c950896..962f64f8a 100644 --- a/launcher/src/main/java/com/skcraft/launcher/Launcher.java +++ b/launcher/src/main/java/com/skcraft/launcher/Launcher.java @@ -415,7 +415,7 @@ public void showLauncherWindow() { */ public static Launcher createFromArguments(String[] args) throws ParameterException, IOException { LauncherArguments options = new LauncherArguments(); - new JCommander(options, args); + new JCommander(options).parse(args); Integer bsVersion = options.getBootstrapVersion(); log.info(bsVersion != null ? "Bootstrap version " + bsVersion + " detected" : "Not bootstrapped"); diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/MicrosoftLoginService.java b/launcher/src/main/java/com/skcraft/launcher/auth/MicrosoftLoginService.java index b79aa32e6..5244b2ac4 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/MicrosoftLoginService.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/MicrosoftLoginService.java @@ -1,7 +1,7 @@ package com.skcraft.launcher.auth; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.skcraft.launcher.auth.microsoft.MicrosoftWebAuthorizer; import com.skcraft.launcher.auth.microsoft.MinecraftServicesAuthorizer; @@ -163,7 +163,7 @@ public SavedSession toSavedSession() { } @Data - @JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class) + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) @JsonIgnoreProperties(ignoreUnknown = true) private static class TokenError { private String error; diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/McAuthResponse.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/McAuthResponse.java index 768c05fcf..c047d12fe 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/McAuthResponse.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/McAuthResponse.java @@ -2,12 +2,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import lombok.Data; @Data -@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class) +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) @JsonIgnoreProperties(ignoreUnknown = true) public class McAuthResponse { private String accessToken; diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/TokenResponse.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/TokenResponse.java index d6aeb60be..2348afc02 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/TokenResponse.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/TokenResponse.java @@ -1,12 +1,12 @@ package com.skcraft.launcher.auth.microsoft.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import lombok.Data; @Data -@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class) +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) @JsonIgnoreProperties(ignoreUnknown = true) public class TokenResponse { private String tokenType; diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XblAuthProperties.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XblAuthProperties.java index 141468784..989187564 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XblAuthProperties.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XblAuthProperties.java @@ -1,12 +1,12 @@ package com.skcraft.launcher.auth.microsoft.model; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import lombok.Data; import lombok.NonNull; @Data -@JsonNaming(PropertyNamingStrategy.PascalCaseStrategy.class) +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class XblAuthProperties { private String authMethod = "RPS"; private String siteName = "user.auth.xboxlive.com"; diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XboxAuthRequest.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XboxAuthRequest.java index 53c449815..388835748 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XboxAuthRequest.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XboxAuthRequest.java @@ -1,12 +1,12 @@ package com.skcraft.launcher.auth.microsoft.model; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import lombok.Data; import lombok.NonNull; @Data -@JsonNaming(PropertyNamingStrategy.PascalCaseStrategy.class) +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class XboxAuthRequest { @NonNull private T properties; private String relyingParty = "http://auth.xboxlive.com"; diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XboxAuthResponse.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XboxAuthResponse.java index c7893a81a..e989e3889 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XboxAuthResponse.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XboxAuthResponse.java @@ -2,14 +2,14 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import lombok.Data; import java.util.List; @Data -@JsonNaming(PropertyNamingStrategy.PascalCaseStrategy.class) +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) @JsonIgnoreProperties(ignoreUnknown = true) public class XboxAuthResponse { private String token; diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XstsAuthProperties.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XstsAuthProperties.java index 63fcef881..5d59693b2 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XstsAuthProperties.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XstsAuthProperties.java @@ -1,6 +1,6 @@ package com.skcraft.launcher.auth.microsoft.model; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import lombok.Data; @@ -8,7 +8,7 @@ import java.util.List; @Data -@JsonNaming(PropertyNamingStrategy.PascalCaseStrategy.class) +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class XstsAuthProperties { private String sandboxId = "RETAIL"; private List userTokens; diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XstsError.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XstsError.java index d279d42b6..aec313ff8 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XstsError.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/model/XstsError.java @@ -2,12 +2,12 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import lombok.Data; @Data -@JsonNaming(PropertyNamingStrategy.PascalCaseStrategy.class) +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) @JsonIgnoreProperties(ignoreUnknown = true) public class XstsError { @JsonProperty("XErr") diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/ArgumentValueDeserializer.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/ArgumentValueDeserializer.java index 7bf74d471..de9931300 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/ArgumentValueDeserializer.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/ArgumentValueDeserializer.java @@ -30,6 +30,6 @@ public List deserialize(JsonParser jp, DeserializationContext ctxt) thro return Lists.newArrayList(value); } - throw new InvalidFormatException("Invalid JSON type for deserializer (not string or array)", null, List.class); + throw new InvalidFormatException(jp, "Invalid JSON type for deserializer (not string or array)", null, List.class); } } diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/MinecraftArgumentsDeserializer.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/MinecraftArgumentsDeserializer.java index a6436a260..f297d372e 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/MinecraftArgumentsDeserializer.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/MinecraftArgumentsDeserializer.java @@ -26,6 +26,6 @@ public GameArgument deserialize(JsonParser jp, DeserializationContext ctxt) thro return new GameArgument(argument); } - throw new InvalidFormatException("Invalid JSON type for deserializer (not string or object)", null, GameArgument.class); + throw new InvalidFormatException(jp, "Invalid JSON type for deserializer (not string or object)", null, GameArgument.class); } } diff --git a/launcher/src/main/java/com/skcraft/launcher/persistence/Persistence.java b/launcher/src/main/java/com/skcraft/launcher/persistence/Persistence.java index 8f1e264bf..529a2b5a0 100644 --- a/launcher/src/main/java/com/skcraft/launcher/persistence/Persistence.java +++ b/launcher/src/main/java/com/skcraft/launcher/persistence/Persistence.java @@ -7,8 +7,8 @@ package com.skcraft.launcher.persistence; import com.fasterxml.jackson.core.PrettyPrinter; +import com.fasterxml.jackson.core.util.DefaultIndenter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter.Lf2SpacesIndenter; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.io.ByteSink; import com.google.common.io.ByteSource; @@ -43,7 +43,7 @@ public final class Persistence { static { L2F_LIST_PRETTY_PRINTER = new DefaultPrettyPrinter(); - L2F_LIST_PRETTY_PRINTER.indentArraysWith(Lf2SpacesIndenter.instance); + L2F_LIST_PRETTY_PRINTER.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE); } private Persistence() { diff --git a/launcher/src/main/java/com/skcraft/launcher/util/HttpRequest.java b/launcher/src/main/java/com/skcraft/launcher/util/HttpRequest.java index 6bf14572a..e97b55814 100644 --- a/launcher/src/main/java/com/skcraft/launcher/util/HttpRequest.java +++ b/launcher/src/main/java/com/skcraft/launcher/util/HttpRequest.java @@ -558,7 +558,7 @@ public T asJson(Class cls) throws IOException { * @return the object * @throws java.io.IOException on I/O error */ - public T asJson(TypeReference type) throws IOException { + public T asJson(TypeReference type) throws IOException { return mapper.readValue(asString("UTF-8"), type); } From 0a5abee9561df3c9b278c82ade2edaec329a6b0b Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Wed, 27 Apr 2022 01:53:14 +0100 Subject: [PATCH 13/45] Make the build output one jar file per subproject again --- creator-tools/build.gradle | 3 ++- launcher-bootstrap/build.gradle | 1 + launcher-builder/build.gradle | 1 + launcher-fancy/build.gradle | 3 ++- launcher/build.gradle | 1 + 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/creator-tools/build.gradle b/creator-tools/build.gradle index 94aa5e712..72f9ff296 100644 --- a/creator-tools/build.gradle +++ b/creator-tools/build.gradle @@ -11,7 +11,7 @@ application { } dependencies { - implementation project(':launcher-builder') + implementation project(path: ':launcher-builder', configuration: 'shadow') implementation 'org.eclipse.jetty:jetty-server:9.3.1.v20150714' implementation 'com.jidesoft:jide-oss:3.6.18' } @@ -25,6 +25,7 @@ processResources { } shadowJar { + archiveClassifier.set("") } build { diff --git a/launcher-bootstrap/build.gradle b/launcher-bootstrap/build.gradle index 872063e26..12969d60d 100644 --- a/launcher-bootstrap/build.gradle +++ b/launcher-bootstrap/build.gradle @@ -22,6 +22,7 @@ processResources { } shadowJar { + archiveClassifier.set("") } build { diff --git a/launcher-builder/build.gradle b/launcher-builder/build.gradle index 008cfa69e..a3b56238f 100644 --- a/launcher-builder/build.gradle +++ b/launcher-builder/build.gradle @@ -15,6 +15,7 @@ dependencies { } shadowJar { + archiveClassifier.set("") } build { diff --git a/launcher-fancy/build.gradle b/launcher-fancy/build.gradle index bbd656125..4c38b22b0 100644 --- a/launcher-fancy/build.gradle +++ b/launcher-fancy/build.gradle @@ -16,11 +16,12 @@ repositories { } dependencies { - implementation project(':launcher') + implementation project(path: ':launcher', configuration: 'shadow') implementation 'io.github.cottonmc.insubstantial:substance:7.3.1-SNAPSHOT' } shadowJar { + archiveClassifier.set("") } build { diff --git a/launcher/build.gradle b/launcher/build.gradle index 28c4bc651..b41115ad2 100644 --- a/launcher/build.gradle +++ b/launcher/build.gradle @@ -32,6 +32,7 @@ processResources { } shadowJar { + archiveClassifier.set("") } build { From 2fe96e443567dbf503d060d480e842c7aed2e6fb Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Wed, 27 Apr 2022 02:02:47 +0100 Subject: [PATCH 14/45] Fix NPE when manifests don't contain JVM arguments Jackson upgrade exposed/introduced a bug where the JVM half of Minecraft arguments could end up missing in some cases. Not exactly sure if the field was null on the serializing side or just an empty array, but we just fix it by always initializing the fields. --- .../com/skcraft/launcher/model/loader/VersionInfo.java | 2 -- .../launcher/model/minecraft/MinecraftArguments.java | 5 +++-- .../skcraft/launcher/model/minecraft/VersionManifest.java | 7 ++++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/model/loader/VersionInfo.java b/launcher/src/main/java/com/skcraft/launcher/model/loader/VersionInfo.java index 7d383bcd0..6b52672a6 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/loader/VersionInfo.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/loader/VersionInfo.java @@ -14,7 +14,6 @@ import com.skcraft.launcher.model.minecraft.MinecraftArguments; import lombok.Data; -import java.util.ArrayList; import java.util.List; @Data @@ -29,7 +28,6 @@ public class VersionInfo { public void setMinecraftArguments(String argumentString) { MinecraftArguments minecraftArguments = new MinecraftArguments(); - minecraftArguments.setGameArguments(new ArrayList()); for (String arg : Splitter.on(' ').split(argumentString)) { minecraftArguments.getGameArguments().add(new GameArgument(arg)); diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/MinecraftArguments.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/MinecraftArguments.java index 801e2d244..077f7a4f1 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/MinecraftArguments.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/MinecraftArguments.java @@ -9,6 +9,7 @@ import com.skcraft.launcher.model.minecraft.mapper.MinecraftArgumentsSerializer; import lombok.Data; +import java.util.ArrayList; import java.util.List; @Data @@ -18,12 +19,12 @@ public class MinecraftArguments { @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) @JsonSerialize(contentUsing = MinecraftArgumentsSerializer.class) @JsonDeserialize(contentUsing = MinecraftArgumentsDeserializer.class) - private List gameArguments; + private List gameArguments = new ArrayList<>(); @JsonProperty("jvm") @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) @JsonSerialize(contentUsing = MinecraftArgumentsSerializer.class) @JsonDeserialize(contentUsing = MinecraftArgumentsDeserializer.class) - private List jvmArguments; + private List jvmArguments = new ArrayList<>(); } diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/VersionManifest.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/VersionManifest.java index dd3cf63c6..f1ffa2e98 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/VersionManifest.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/VersionManifest.java @@ -12,7 +12,10 @@ import com.skcraft.launcher.model.loader.SidedData; import lombok.Data; -import java.util.*; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; @Data @JsonIgnoreProperties(ignoreUnknown = true) @@ -50,8 +53,6 @@ public Library findLibrary(String name) { public void setMinecraftArguments(String minecraftArguments) { MinecraftArguments result = new MinecraftArguments(); - result.setGameArguments(new ArrayList()); - result.setJvmArguments(new ArrayList()); for (String arg : Splitter.on(' ').split(minecraftArguments)) { result.getGameArguments().add(new GameArgument(arg)); From debd8224477518457bf06729616fe5ee4fafe16f Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Sun, 1 May 2022 15:34:48 +0100 Subject: [PATCH 15/45] Hotfix package builder emitting JSON with missing keys for empty values The meaning of `mapper.setSerializationInclusion` changed with the Jackson upgrade, which meant that empty collections were being fully stripped from the output. Fix by changing the strategy to NON_ABSENT, which only strips nulls and "absent" values like Optional.absent --- .../main/java/com/skcraft/launcher/builder/PackageBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java index 6b85f989a..422248f7d 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java @@ -407,7 +407,7 @@ public static void main(String[] args) throws IOException, InterruptedException // Initialize SimpleLogFormatter.configureGlobalLogger(); ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); + mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT); Manifest manifest = new Manifest(); manifest.setMinimumVersion(Manifest.MIN_PROTOCOL_VERSION); From 39487dda3ea302a94427433fe2e083620dd94a24 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Tue, 3 May 2022 21:49:26 +0100 Subject: [PATCH 16/45] Make assets tree builder use hardlinks if available --- .../java/com/skcraft/launcher/AssetsRoot.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/AssetsRoot.java b/launcher/src/main/java/com/skcraft/launcher/AssetsRoot.java index 2bf64c798..247188f8e 100644 --- a/launcher/src/main/java/com/skcraft/launcher/AssetsRoot.java +++ b/launcher/src/main/java/com/skcraft/launcher/AssetsRoot.java @@ -6,7 +6,6 @@ package com.skcraft.launcher; -import com.google.common.io.Files; import com.skcraft.concurrency.ProgressObservable; import com.skcraft.launcher.model.minecraft.Asset; import com.skcraft.launcher.model.minecraft.AssetsIndex; @@ -18,6 +17,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.util.Map; import java.util.logging.Level; @@ -101,6 +101,7 @@ public AssetsTreeBuilder(AssetsIndex index, File destDir) { public File build() throws IOException, LauncherException { AssetsRoot.log.info("Building asset virtual tree at '" + destDir.getAbsolutePath() + "'..."); + boolean supportsLinks = true; for (Map.Entry entry : index.getObjects().entrySet()) { File objectPath = getObjectPath(entry.getValue()); File virtualPath = new File(destDir, entry.getKey()); @@ -114,7 +115,17 @@ public File build() throws IOException, LauncherException { throw new LauncherException("Missing object " + objectPath.getAbsolutePath(), message); } - Files.copy(objectPath, virtualPath); + if (supportsLinks) { + try { + Files.createLink(virtualPath.toPath(), objectPath.toPath()); + } catch (UnsupportedOperationException e) { + supportsLinks = false; + } + } + + if (!supportsLinks) { + Files.copy(objectPath.toPath(), virtualPath.toPath()); + } } processed++; } From 23e01defeac21c12836efd0d058c2b54329903b8 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Thu, 5 May 2022 00:54:02 +0100 Subject: [PATCH 17/45] Add support for UTF-8 encoded locale files Fixes #467 --- .../launcher/util/LocaleEncodingControl.java | 81 +++++++++++++++++++ .../skcraft/launcher/util/SharedLocale.java | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java diff --git a/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java b/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java new file mode 100644 index 000000000..144badf22 --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java @@ -0,0 +1,81 @@ +package com.skcraft.launcher.util; + +import lombok.extern.java.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Locale; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +@Log +public class LocaleEncodingControl extends ResourceBundle.Control { + @Override + public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException { + if (!format.equals("java.properties")) { + return super.newBundle(baseName, locale, format, loader, reload); + } + + String bundleName = this.toBundleName(baseName, locale); + String resourceName = this.toResourceName(bundleName, "properties"); + + InputStream is = this.getResourceAsStream(resourceName, loader, reload); + if (is == null) { + return null; + } + + // Let's do the timewalk + boolean isUtf8; + is.mark(3); + { + byte[] buf = new byte[3]; + int read = 0; + while (read < 3) { + read = is.read(buf); + } + + // the BOM is 0xEF,0xBB,0xBF + isUtf8 = buf[0] == (byte) 0xEF && buf[1] == (byte) 0xBB && buf[2] == (byte) 0xBF; + } + is.reset(); + + if (isUtf8) { + log.info("Found UTF-8 locale file " + resourceName); + } + + Charset charset = isUtf8 ? StandardCharsets.UTF_8 : StandardCharsets.ISO_8859_1; + Reader reader = new InputStreamReader(is, charset); + + try { + PropertyResourceBundle bundle = new PropertyResourceBundle(reader); + reader.close(); + + return bundle; + } finally { + // Just in case of exception... + reader.close(); + } + } + + private InputStream getResourceAsStream(String resourceName, ClassLoader loader, boolean reload) throws IOException { + if (reload) { + URL url = loader.getResource(resourceName); + if (url != null) { + URLConnection conn = url.openConnection(); + if (conn != null) { + conn.setUseCaches(false); + + return conn.getInputStream(); + } + } + } + + return loader.getResourceAsStream(resourceName); + } +} diff --git a/launcher/src/main/java/com/skcraft/launcher/util/SharedLocale.java b/launcher/src/main/java/com/skcraft/launcher/util/SharedLocale.java index 425a24e8c..a58b415a2 100644 --- a/launcher/src/main/java/com/skcraft/launcher/util/SharedLocale.java +++ b/launcher/src/main/java/com/skcraft/launcher/util/SharedLocale.java @@ -96,7 +96,7 @@ public static boolean loadBundle(@NonNull String baseName, @NonNull Locale local try { SharedLocale.locale = locale; bundle = ResourceBundle.getBundle(baseName, locale, - SharedLocale.class.getClassLoader()); + SharedLocale.class.getClassLoader(), new LocaleEncodingControl()); return true; } catch (MissingResourceException e) { log.log(Level.SEVERE, "Failed to load resource bundle", e); From 90ff8dfdb7819a3f4546d921a080f9ed8503dbc8 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Tue, 10 May 2022 10:05:06 +0100 Subject: [PATCH 18/45] Fix locale errors due to inconsistent mark/reset support Fixes #470 --- .../launcher/util/LocaleEncodingControl.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java b/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java index 144badf22..33d942040 100644 --- a/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java +++ b/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java @@ -2,10 +2,7 @@ import lombok.extern.java.Log; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; +import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; @@ -30,27 +27,32 @@ public ResourceBundle newBundle(String baseName, Locale locale, String format, C return null; } + BufferedInputStream bis = new BufferedInputStream(is); + // Let's do the timewalk boolean isUtf8; - is.mark(3); + bis.mark(3); { byte[] buf = new byte[3]; - int read = 0; - while (read < 3) { - read = is.read(buf); + int nread = 0; + while (nread < 3) { + int read = bis.read(buf); + + if (read == -1) throw new EOFException("Locale file is truncated or empty!"); + nread += read; } // the BOM is 0xEF,0xBB,0xBF isUtf8 = buf[0] == (byte) 0xEF && buf[1] == (byte) 0xBB && buf[2] == (byte) 0xBF; } - is.reset(); + bis.reset(); if (isUtf8) { log.info("Found UTF-8 locale file " + resourceName); } Charset charset = isUtf8 ? StandardCharsets.UTF_8 : StandardCharsets.ISO_8859_1; - Reader reader = new InputStreamReader(is, charset); + Reader reader = new InputStreamReader(bis, charset); try { PropertyResourceBundle bundle = new PropertyResourceBundle(reader); From b8a6769c43f63c433bae43f4bc4ec8a078739653 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Tue, 10 May 2022 10:22:58 +0100 Subject: [PATCH 19/45] Fix stream-reading logic in locale control It's pretty likely that we would always read 3 bytes but let's do it properly --- .../launcher/util/LocaleEncodingControl.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java b/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java index 33d942040..72e5932e1 100644 --- a/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java +++ b/launcher/src/main/java/com/skcraft/launcher/util/LocaleEncodingControl.java @@ -34,13 +34,7 @@ public ResourceBundle newBundle(String baseName, Locale locale, String format, C bis.mark(3); { byte[] buf = new byte[3]; - int nread = 0; - while (nread < 3) { - int read = bis.read(buf); - - if (read == -1) throw new EOFException("Locale file is truncated or empty!"); - nread += read; - } + readFully(bis, buf); // the BOM is 0xEF,0xBB,0xBF isUtf8 = buf[0] == (byte) 0xEF && buf[1] == (byte) 0xBB && buf[2] == (byte) 0xBF; @@ -80,4 +74,19 @@ private InputStream getResourceAsStream(String resourceName, ClassLoader loader, return loader.getResourceAsStream(resourceName); } + + private void readFully(InputStream is, byte[] buf) throws IOException { + int offset = 0; + int length = buf.length; + + while (length > 0) { + int n = is.read(buf, offset, length); + if (n == -1) { + throw new EOFException(); + } + + offset += n; + length -= n; + } + } } From 1c64de1df00e108ea46f6ab95bd042344c46d2e1 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Mon, 30 May 2022 20:58:40 +0100 Subject: [PATCH 20/45] GH-472 Add warning popup for mismatched Java versions Closes #472 --- .../launcher/launch/LaunchSupervisor.java | 41 ++++++++++++++++++- .../com/skcraft/launcher/launch/Runner.java | 30 ++++++++++++-- .../skcraft/launcher/swing/SwingHelper.java | 8 +++- .../skcraft/launcher/lang/Launcher.properties | 3 ++ 4 files changed, 76 insertions(+), 6 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/LaunchSupervisor.java b/launcher/src/main/java/com/skcraft/launcher/launch/LaunchSupervisor.java index 9dd8a2726..887e62055 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/LaunchSupervisor.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/LaunchSupervisor.java @@ -16,11 +16,14 @@ import com.skcraft.launcher.dialog.AccountSelectDialog; import com.skcraft.launcher.dialog.ProgressDialog; import com.skcraft.launcher.launch.LaunchOptions.UpdatePolicy; +import com.skcraft.launcher.launch.runtime.JavaRuntime; +import com.skcraft.launcher.model.minecraft.JavaVersion; import com.skcraft.launcher.persistence.Persistence; import com.skcraft.launcher.swing.SwingHelper; import com.skcraft.launcher.update.Updater; import com.skcraft.launcher.util.SharedLocale; import com.skcraft.launcher.util.SwingExecutor; +import lombok.RequiredArgsConstructor; import lombok.extern.java.Log; import org.apache.commons.io.FileUtils; @@ -29,6 +32,8 @@ import java.io.File; import java.io.IOException; import java.util.Date; +import java.util.concurrent.ExecutionException; +import java.util.function.BiPredicate; import java.util.logging.Level; import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor; @@ -119,7 +124,7 @@ private void launch(Window window, Instance instance, Session session, final Lau final File extractDir = launcher.createExtractDir(); // Get the process - Runner task = new Runner(launcher, instance, session, extractDir); + Runner task = new Runner(launcher, instance, session, extractDir, new RuntimeVerifier(instance)); ObservableFuture processFuture = new ObservableFuture( launcher.getExecutor().submit(task), task); @@ -169,4 +174,38 @@ public void run() { } }, sameThreadExecutor()); } + + @RequiredArgsConstructor + static class RuntimeVerifier implements BiPredicate { + private final Instance instance; + + @Override + public boolean test(JavaRuntime javaRuntime, JavaVersion javaVersion) { + ListenableFuture fut = SwingExecutor.INSTANCE.submit(() -> { + Object[] options = new Object[]{ + tr("button.cancel"), + tr("button.launchAnyway"), + }; + + String message = tr("runner.wrongJavaVersion", + instance.getTitle(), javaVersion.getMajorVersion(), javaRuntime.getVersion()); + int picked = JOptionPane.showOptionDialog(null, + SwingHelper.htmlWrap(message), + tr("launcher.javaMismatchTitle"), + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + options, + null); + + return picked == 1; + }); + + try { + return fut.get(); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException(e); + } + } + } } diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java b/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java index 27d98e7f6..abbee20bf 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java @@ -37,6 +37,8 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.function.BiPredicate; import static com.skcraft.launcher.LauncherUtils.checkInterrupted; import static com.skcraft.launcher.util.SharedLocale.tr; @@ -54,6 +56,7 @@ public class Runner implements Callable, ProgressObservable { private final Instance instance; private final Session session; private final File extractDir; + private final BiPredicate javaRuntimeMismatch; @Getter @Setter private Environment environment = Environment.getInstance(); private VersionManifest versionManifest; @@ -66,18 +69,20 @@ public class Runner implements Callable, ProgressObservable { /** * Create a new instance launcher. - * - * @param launcher the launcher + * @param launcher the launcher * @param instance the instance * @param session the session * @param extractDir the directory to extract to + * @param javaRuntimeMismatch */ public Runner(@NonNull Launcher launcher, @NonNull Instance instance, - @NonNull Session session, @NonNull File extractDir) { + @NonNull Session session, @NonNull File extractDir, + BiPredicate javaRuntimeMismatch) { this.launcher = launcher; this.instance = instance; this.session = session; this.extractDir = extractDir; + this.javaRuntimeMismatch = javaRuntimeMismatch; this.featureList = new FeatureList.Mutable(); } @@ -149,6 +154,8 @@ public Process call() throws Exception { callLaunchModifier(); + verifyJavaRuntime(); + ProcessBuilder processBuilder = new ProcessBuilder(builder.buildCommand()); processBuilder.directory(instance.getContentDir()); Runner.log.info("Launching: " + builder); @@ -166,6 +173,23 @@ private void callLaunchModifier() { instance.modify(builder); } + private void verifyJavaRuntime() { + JavaRuntime pickedRuntime = builder.getRuntime(); + JavaVersion targetVersion = versionManifest.getJavaVersion(); + + if (pickedRuntime == null || targetVersion == null) { + return; + } + + if (pickedRuntime.getMajorVersion() != targetVersion.getMajorVersion()) { + boolean launchAnyway = javaRuntimeMismatch.test(pickedRuntime, targetVersion); + + if (!launchAnyway) { + throw new CancellationException("Launch cancelled by user."); + } + } + } + /** * Add platform-specific arguments. */ diff --git a/launcher/src/main/java/com/skcraft/launcher/swing/SwingHelper.java b/launcher/src/main/java/com/skcraft/launcher/swing/SwingHelper.java index b8239dfe3..1ee7a1c50 100644 --- a/launcher/src/main/java/com/skcraft/launcher/swing/SwingHelper.java +++ b/launcher/src/main/java/com/skcraft/launcher/swing/SwingHelper.java @@ -70,6 +70,11 @@ public static String htmlEscape(String str) { .replace("&", "&"); } + public static String htmlWrap(String message) { + // To force the label to wrap, convert the message to broken HTML + return "
" + htmlEscape(message); + } + public static void setClipboard(String text) { Toolkit.getDefaultToolkit().getSystemClipboard().setContents( new StringSelection(text), clipboardOwner); @@ -189,8 +194,7 @@ public static void showMessageDialog(final Component parentComponent, final int messageType) { if (SwingUtilities.isEventDispatchThread()) { - // To force the label to wrap, convert the message to broken HTML - String htmlMessage = "
" + htmlEscape(message); + String htmlMessage = htmlWrap(message); JPanel panel = new JPanel(new BorderLayout(0, detailsText != null ? 20 : 0)); diff --git a/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties b/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties index 652c77411..96f176642 100644 --- a/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties +++ b/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties @@ -23,6 +23,7 @@ errors.selfUpdateCheckError=Checking for an update to the launcher has failed. button.cancel=Cancel button.ok=OK button.save=Save +button.launchAnyway=Launch Anyway options.title = Options options.useProxyCheck = Use following proxy in Minecraft @@ -88,6 +89,7 @@ launcher.noInstanceError=Please select a modpack to launch. launcher.noInstanceTitle=No Modpack Selected launcher.launchingTItle=Launching the game... launcher.launchingStatus=Launching ''{0}''. Please wait. +launcher.javaMismatchTitle=Java version warning launcher.modpackColumn=Modpack launcher.notInstalledHint=(not installed) launcher.requiresUpdateHint=(requires update) @@ -191,6 +193,7 @@ runner.updateRequired=This instance must be updated before it can be run. runner.missingLibrary={0} needs to be relaunched and updated because the library ''{1}'' is missing. runner.missingAssetsIndex={0} needs to be relaunched and updated because its asset index is missing. runner.corruptAssetsIndex={0} needs to be relaunched and updated because its asset index is corrupt. +runner.wrongJavaVersion=Instance ''{0}'' requires Java version {1}, but could only find {2}. assets.expanding1=Expanding {0} asset... ({1} remaining) assets.expandingN=Expanding {0} assets... ({1} remaining) From 4decceb5c9befcab93e23ff8e1e379bf850f3223 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Mon, 30 May 2022 21:11:41 +0100 Subject: [PATCH 21/45] GH-471 Re-label configuration option as "Fallback Java Runtime" --- .../com/skcraft/launcher/dialog/InstanceSettingsDialog.java | 2 +- .../resources/com/skcraft/launcher/lang/Launcher.properties | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/dialog/InstanceSettingsDialog.java b/launcher/src/main/java/com/skcraft/launcher/dialog/InstanceSettingsDialog.java index f261e95cf..9518024ca 100644 --- a/launcher/src/main/java/com/skcraft/launcher/dialog/InstanceSettingsDialog.java +++ b/launcher/src/main/java/com/skcraft/launcher/dialog/InstanceSettingsDialog.java @@ -57,7 +57,7 @@ private void initComponents() { javaRuntimeBox.setModel(new DefaultComboBoxModel<>(javaRuntimes)); runtimePanel.addRow(enableCustomRuntime); - runtimePanel.addRow(new JLabel(SharedLocale.tr("options.jvmPath")), javaRuntimeBox); + runtimePanel.addRow(new JLabel(SharedLocale.tr("options.jvmRuntime")), javaRuntimeBox); runtimePanel.addRow(new JLabel(SharedLocale.tr("options.jvmArguments")), javaArgsBox); okButton.setMargin(new Insets(0, 10, 0, 10)); diff --git a/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties b/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties index 96f176642..ef48f3c4b 100644 --- a/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties +++ b/launcher/src/main/resources/com/skcraft/launcher/lang/Launcher.properties @@ -27,7 +27,8 @@ button.launchAnyway=Launch Anyway options.title = Options options.useProxyCheck = Use following proxy in Minecraft -options.jvmPath=Java Runtime\: +options.jvmPath=Fallback Java Runtime\: +options.jvmRuntime=Java Runtime\: options.jvmArguments=JVM arguments\: options.64BitJavaWarning=Make sure to have 64-bit Java installed if you are planning to set the memory limits higher. options.minMemory=Minimum memory (MB)\: From 16f44a860c494746a01aa4f7fa2a6e32624de133 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Mon, 30 May 2022 23:53:55 +0100 Subject: [PATCH 22/45] GH-473 Fix extra launcher windows opening after java version warning --- .../launcher/launch/LaunchSupervisor.java | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/LaunchSupervisor.java b/launcher/src/main/java/com/skcraft/launcher/launch/LaunchSupervisor.java index 887e62055..09f2f23c4 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/LaunchSupervisor.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/LaunchSupervisor.java @@ -14,6 +14,7 @@ import com.skcraft.launcher.Launcher; import com.skcraft.launcher.auth.Session; import com.skcraft.launcher.dialog.AccountSelectDialog; +import com.skcraft.launcher.dialog.ProcessConsoleFrame; import com.skcraft.launcher.dialog.ProgressDialog; import com.skcraft.launcher.launch.LaunchOptions.UpdatePolicy; import com.skcraft.launcher.launch.runtime.JavaRuntime; @@ -27,11 +28,13 @@ import lombok.extern.java.Log; import org.apache.commons.io.FileUtils; +import javax.annotation.Nullable; import javax.swing.*; import java.awt.*; import java.io.File; import java.io.IOException; import java.util.Date; +import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.function.BiPredicate; import java.util.logging.Level; @@ -136,12 +139,7 @@ private void launch(Window window, Instance instance, Session session, final Lau Futures.addCallback(processFuture, new FutureCallback() { @Override public void onSuccess(Process result) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - listener.gameStarted(); - } - }); + SwingUtilities.invokeLater(listener::gameStarted); } @Override @@ -150,29 +148,36 @@ public void onFailure(Throwable t) { }); // Watch the created process - ListenableFuture future = Futures.transform( + ListenableFuture future = Futures.transform( processFuture, new LaunchProcessHandler(launcher), launcher.getExecutor()); SwingHelper.addErrorDialogCallback(null, future); // Clean up at the very end - future.addListener(new Runnable() { + future.addListener(() -> { + try { + log.info("Process ended; cleaning up " + extractDir.getAbsolutePath()); + FileUtils.deleteDirectory(extractDir); + } catch (IOException e) { + log.log(Level.WARNING, "Failed to clean up " + extractDir.getAbsolutePath(), e); + } + }, sameThreadExecutor()); + + // Hook up launch listener + Futures.addCallback(future, new FutureCallback() { @Override - public void run() { - try { - log.info("Process ended; cleaning up " + extractDir.getAbsolutePath()); - FileUtils.deleteDirectory(extractDir); - } catch (IOException e) { - log.log(Level.WARNING, "Failed to clean up " + extractDir.getAbsolutePath(), e); - } + public void onSuccess(@Nullable ProcessConsoleFrame result) { + // gameStarted was only invoked on success above, so only call gameClosed on success + listener.gameClosed(); + } - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - listener.gameClosed(); - } - }); + @Override + public void onFailure(Throwable t) { + // likely user cancellation + if (!(t instanceof CancellationException)) { + log.info("Process failure: " + t.getLocalizedMessage()); + } } - }, sameThreadExecutor()); + }, SwingExecutor.INSTANCE); } @RequiredArgsConstructor From 2a6c5ee015bf0ec05262dd888ae83dd48f0cce3a Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Sun, 7 Aug 2022 03:15:47 +0100 Subject: [PATCH 23/45] GH-481 Add Quilt loader support ... with a caveat that it may break in future due to Quilt's broken metadata --- .../launcher/builder/PackageBuilder.java | 12 +++-- .../loaders/FabricLoaderProcessor.java | 51 +++++++++++++++---- .../launcher/model/loader/FabricMod.java | 2 +- .../launcher/model/loader/QuiltMod.java | 29 +++++++++++ .../launcher/model/loader/Versionable.java | 5 ++ .../skcraft/launcher/util/HttpRequest.java | 22 ++++++++ 6 files changed, 106 insertions(+), 15 deletions(-) create mode 100644 launcher/src/main/java/com/skcraft/launcher/model/loader/QuiltMod.java create mode 100644 launcher/src/main/java/com/skcraft/launcher/model/loader/Versionable.java diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java index 422248f7d..dd208777d 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java @@ -168,7 +168,9 @@ private void processLoader(LinkedHashSet loaderLibraries, File file, Fi processor = new ModernForgeLoaderProcessor(); } } else if (BuilderUtils.getZipEntry(jarFile, "fabric-installer.json") != null) { - processor = new FabricLoaderProcessor(); + processor = new FabricLoaderProcessor(FabricLoaderProcessor.Variant.FABRIC); + } else if (BuilderUtils.getZipEntry(jarFile, "quilt_installer.json") != null) { + processor = new FabricLoaderProcessor(FabricLoaderProcessor.Variant.QUILT); } } finally { closer.close(); @@ -205,8 +207,8 @@ public void downloadLibraries(File librariesDir) throws IOException, Interrupted Files.createParentDirs(outputPath); boolean found = false; - // Try just the URL, it might be a full URL to the file - if (!artifact.getUrl().isEmpty()) { + // If URL doesn't end with a /, it might be the direct file + if (!artifact.getUrl().endsWith("/")) { found = tryDownloadLibrary(library, artifact, artifact.getUrl(), outputPath); } @@ -261,7 +263,9 @@ private boolean tryDownloadLibrary(Library library, Library.Artifact artifact, S try { log.info("Downloading library " + library.getName() + " from " + url + "..."); - HttpRequest.get(url).execute().expectResponseCode(200).saveContent(tempFile); + HttpRequest.get(url).execute().expectResponseCode(200) + .expectContentType("application/java-archive", "application/octet-stream") + .saveContent(tempFile); } catch (IOException e) { log.info("Could not get file from " + url + ": " + e.getMessage()); return false; diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/FabricLoaderProcessor.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/FabricLoaderProcessor.java index a5d3cfb28..f3362a6a3 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/FabricLoaderProcessor.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/FabricLoaderProcessor.java @@ -4,10 +4,13 @@ import com.google.common.io.Closer; import com.skcraft.launcher.builder.BuilderUtils; import com.skcraft.launcher.model.loader.FabricMod; +import com.skcraft.launcher.model.loader.QuiltMod; +import com.skcraft.launcher.model.loader.Versionable; import com.skcraft.launcher.model.minecraft.Library; import com.skcraft.launcher.model.minecraft.VersionManifest; import com.skcraft.launcher.model.modpack.Manifest; import com.skcraft.launcher.util.HttpRequest; +import lombok.RequiredArgsConstructor; import lombok.extern.java.Log; import java.io.File; @@ -18,7 +21,10 @@ import java.util.zip.ZipEntry; @Log +@RequiredArgsConstructor public class FabricLoaderProcessor implements ILoaderProcessor { + private final Variant variant; + @Override public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapper, File baseDir) throws IOException { JarFile jarFile = new JarFile(loaderJar); @@ -26,24 +32,23 @@ public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapp Closer closer = Closer.create(); try { - String loaderVersion; + Versionable loaderMod; - ZipEntry modEntry = BuilderUtils.getZipEntry(jarFile, "fabric.mod.json"); + ZipEntry modEntry = BuilderUtils.getZipEntry(jarFile, variant.modJsonName); if (modEntry != null) { InputStreamReader reader = new InputStreamReader(jarFile.getInputStream(modEntry)); - FabricMod loaderMod = mapper.readValue( - BuilderUtils.readStringFromStream(closer.register(reader)), FabricMod.class); - loaderVersion = loaderMod.getVersion(); + loaderMod = mapper.readValue( + BuilderUtils.readStringFromStream(closer.register(reader)), variant.mappedClass); } else { - log.warning("Fabric loader has no 'fabric.mod.json' file, is it really a Fabric Loader jar?"); + log.warning(String.format("%s loader has no '%s' file, is it really a %s Loader jar?", + variant.friendlyName, variant.modJsonName, variant.friendlyName)); return null; } - log.info("Downloading fabric metadata..."); + log.info(String.format("Downloading %s metadata...", variant.friendlyName)); URL metaUrl = HttpRequest.url( - String.format("https://meta.fabricmc.net/v2/versions/loader/%s/%s/profile/json", - manifest.getGameVersion(), loaderVersion)); + String.format(variant.metaUrl, manifest.getGameVersion(), loaderMod.getVersion())); VersionManifest fabricManifest = HttpRequest.get(metaUrl) .execute() .expectResponseCode(200) @@ -51,6 +56,20 @@ public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapp .asJson(VersionManifest.class); for (Library library : fabricManifest.getLibraries()) { + // To quote a famous comment: "And here we come upon a sad state of affairs." + // Quilt's meta API returns broken data about how to launch the game. It specifies its own incomplete + // and ultimately broken set of intermediary mappings called "hashed". If the loader finds "hashed" in + // the classpath it tries to use it and blows up because it doesn't work. + // We work around this here by just throwing the hashed library out - they do now at least specify + // fabric's intermediary mappings in the library list, which DO work. + // Historical note: previously they didn't do this! Every launcher that added Quilt support had to add + // a hack that replaced hashed with intermediary! This is a lot of technical debt that is gonna come + // back to bite them in the ass later, because it's all still there! + // TODO pester Quilt again about fixing this.... + if (library.getName().startsWith("org.quiltmc:hashed") && loaderMod instanceof QuiltMod) { + continue; + } + result.getLoaderLibraries().add(library); log.info("Adding loader library " + library.getName()); } @@ -61,7 +80,8 @@ public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapp log.info("Using main class " + mainClass); } } catch (InterruptedException e) { - log.warning("HTTP request to fabric metadata API was interrupted, this will probably not work!"); + log.warning(String.format("HTTP request to %s metadata API was interrupted!", variant.friendlyName)); + throw new IOException(e); } finally { closer.close(); jarFile.close(); @@ -69,4 +89,15 @@ public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapp return result; } + + @RequiredArgsConstructor + public enum Variant { + FABRIC("Fabric", "fabric.mod.json", "https://meta.fabricmc.net/v2/versions/loader/%s/%s/profile/json", FabricMod.class), + QUILT("Quilt", "quilt.mod.json", "https://meta.quiltmc.org/v3/versions/loader/%s/%s/profile/json", QuiltMod.class); + + private final String friendlyName; + private final String modJsonName; + private final String metaUrl; + private final Class mappedClass; + } } diff --git a/launcher/src/main/java/com/skcraft/launcher/model/loader/FabricMod.java b/launcher/src/main/java/com/skcraft/launcher/model/loader/FabricMod.java index c354964f0..0afbb91f0 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/loader/FabricMod.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/loader/FabricMod.java @@ -5,7 +5,7 @@ @Data @JsonIgnoreProperties(ignoreUnknown = true) -public class FabricMod { +public class FabricMod implements Versionable { private String id; private String name; private String version; diff --git a/launcher/src/main/java/com/skcraft/launcher/model/loader/QuiltMod.java b/launcher/src/main/java/com/skcraft/launcher/model/loader/QuiltMod.java new file mode 100644 index 000000000..6d0169b39 --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/model/loader/QuiltMod.java @@ -0,0 +1,29 @@ +package com.skcraft.launcher.model.loader; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class QuiltMod implements Versionable { + @JsonProperty("schema_version") + private int schemaVersion; + + @JsonProperty("quilt_loader") + private Mod meta; + + @Override + public String getVersion() { + return meta.getVersion(); + } + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Mod { + private String version; + + @JsonProperty("intermediate_mappings") + private String intermediateMappings; + } +} diff --git a/launcher/src/main/java/com/skcraft/launcher/model/loader/Versionable.java b/launcher/src/main/java/com/skcraft/launcher/model/loader/Versionable.java new file mode 100644 index 000000000..b2faa2b73 --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/model/loader/Versionable.java @@ -0,0 +1,5 @@ +package com.skcraft.launcher.model.loader; + +public interface Versionable { + String getVersion(); +} diff --git a/launcher/src/main/java/com/skcraft/launcher/util/HttpRequest.java b/launcher/src/main/java/com/skcraft/launcher/util/HttpRequest.java index e97b55814..e1b94d42d 100644 --- a/launcher/src/main/java/com/skcraft/launcher/util/HttpRequest.java +++ b/launcher/src/main/java/com/skcraft/launcher/util/HttpRequest.java @@ -232,6 +232,28 @@ public HttpRequest expectResponseCodeOr(int code, HttpFunc throw exc; } + /** + * Continue if the content type matches, otherwise throw an exception + * + * @param expectedTypes Expected content-type(s) + * @return this object + * @throws IOException Unexpected content-type or other error + */ + public HttpRequest expectContentType(String... expectedTypes) throws IOException { + if (conn == null) throw new IllegalArgumentException("No connection has been made!"); + + String contentType = conn.getHeaderField("Content-Type"); + for (String expectedType : expectedTypes) { + if (expectedType.equals(contentType)) { + return this; + } + } + + close(); + throw new IOException(String.format("Did not get expected content type '%s', instead got '%s'.", + String.join(" | ", expectedTypes), contentType)); + } + /** * Get the response code. * From 460070e82f42e41565d38cfe092bbe0f6ff1db0a Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Thu, 11 Aug 2022 22:59:07 +0100 Subject: [PATCH 24/45] NOISSUE Fix forge manifests with empty artifact URLs failing --- .../java/com/skcraft/launcher/builder/PackageBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java index dd208777d..914ff3c27 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java @@ -206,9 +206,10 @@ public void downloadLibraries(File librariesDir) throws IOException, Interrupted if (!outputPath.exists()) { Files.createParentDirs(outputPath); boolean found = false; + boolean urlEmpty = artifact.getUrl().isEmpty(); // If URL doesn't end with a /, it might be the direct file - if (!artifact.getUrl().endsWith("/")) { + if (!urlEmpty && !artifact.getUrl().endsWith("/")) { found = tryDownloadLibrary(library, artifact, artifact.getUrl(), outputPath); } @@ -221,7 +222,7 @@ public void downloadLibraries(File librariesDir) throws IOException, Interrupted } // Assume artifact URL is a maven repository URL and try that - if (!found) { + if (!found && !urlEmpty) { URL url = LauncherUtils.concat(url(artifact.getUrl()), artifact.getPath()); found = tryDownloadLibrary(library, artifact, url.toString(), outputPath); } From c61575d3e247a3b31ff550d6e94dd1f476bfd98c Mon Sep 17 00:00:00 2001 From: Dreytac Date: Wed, 17 Aug 2022 04:11:31 +1000 Subject: [PATCH 25/45] Allow zip files as libraries. --- .../main/java/com/skcraft/launcher/builder/PackageBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java index 914ff3c27..705735c5b 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java @@ -265,7 +265,7 @@ private boolean tryDownloadLibrary(Library library, Library.Artifact artifact, S try { log.info("Downloading library " + library.getName() + " from " + url + "..."); HttpRequest.get(url).execute().expectResponseCode(200) - .expectContentType("application/java-archive", "application/octet-stream") + .expectContentType("application/java-archive", "application/octet-stream", "application/zip") .saveContent(tempFile); } catch (IOException e) { log.info("Could not get file from " + url + ": " + e.getMessage()); From 13b6a77d7780aa4eb51fd5d7bf92ebb1d6ef0a7a Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Sun, 28 Aug 2022 00:37:36 +0100 Subject: [PATCH 26/45] GH-484 Work around bug with gradle shadow plugin --- build.gradle | 28 ++++++++++++++++++++++++++++ creator-tools/build.gradle | 2 +- launcher-builder/build.gradle | 11 ++++++++--- launcher-fancy/build.gradle | 9 ++++++++- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 19a1c131f..49eea452c 100644 --- a/build.gradle +++ b/build.gradle @@ -38,6 +38,34 @@ subprojects { workingDir = new File(rootDir, "run/") workingDir.mkdirs() } + + // Work around gradle shadow bug + // see https://github.com/johnrengelman/shadow/issues/713 + afterEvaluate { + startScripts { + dependsOn(shadowJar) + } + + distTar { + dependsOn(shadowJar) + } + + distZip { + dependsOn(shadowJar) + } + + startShadowScripts { + dependsOn(jar) + } + + shadowDistTar { + dependsOn(jar) + } + + shadowDistZip { + dependsOn(jar) + } + } } task clean { diff --git a/creator-tools/build.gradle b/creator-tools/build.gradle index 72f9ff296..0905e6d0b 100644 --- a/creator-tools/build.gradle +++ b/creator-tools/build.gradle @@ -11,7 +11,7 @@ application { } dependencies { - implementation project(path: ':launcher-builder', configuration: 'shadow') + implementation project(path: ':launcher-builder') implementation 'org.eclipse.jetty:jetty-server:9.3.1.v20150714' implementation 'com.jidesoft:jide-oss:3.6.18' } diff --git a/launcher-builder/build.gradle b/launcher-builder/build.gradle index a3b56238f..224895771 100644 --- a/launcher-builder/build.gradle +++ b/launcher-builder/build.gradle @@ -15,9 +15,14 @@ dependencies { } shadowJar { + dependsOn ':launcher:shadowJar' archiveClassifier.set("") } -build { - dependsOn(shadowJar) -} +// Work around gradle shadow bug +// see https://github.com/johnrengelman/shadow/issues/713 +startScripts.dependsOn(':launcher:shadowJar') +distTar.dependsOn(':launcher:shadowJar') +distZip.dependsOn(':launcher:shadowJar') + +build.dependsOn(shadowJar) diff --git a/launcher-fancy/build.gradle b/launcher-fancy/build.gradle index 4c38b22b0..e387be495 100644 --- a/launcher-fancy/build.gradle +++ b/launcher-fancy/build.gradle @@ -16,14 +16,21 @@ repositories { } dependencies { - implementation project(path: ':launcher', configuration: 'shadow') + implementation project(path: ':launcher') implementation 'io.github.cottonmc.insubstantial:substance:7.3.1-SNAPSHOT' } shadowJar { + dependsOn ':launcher:shadowJar' archiveClassifier.set("") } +// Work around gradle shadow bug +// see https://github.com/johnrengelman/shadow/issues/713 +startScripts.dependsOn(':launcher:shadowJar') +distTar.dependsOn(':launcher:shadowJar') +distZip.dependsOn(':launcher:shadowJar') + build { dependsOn(shadowJar) } From 68bd6c3522962f1d4a4c73ecd6dbf185799f38e6 Mon Sep 17 00:00:00 2001 From: Magi1053 Date: Thu, 3 Nov 2022 22:06:45 -0500 Subject: [PATCH 27/45] Make the oauth response screen customizable html --- .../launcher/auth/microsoft/OauthHttpHandler.java | 12 +++++++++++- .../main/resources/com/skcraft/launcher/login.html | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 launcher/src/main/resources/com/skcraft/launcher/login.html diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/OauthHttpHandler.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/OauthHttpHandler.java index b7b1e0fc7..7e0ea5943 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/OauthHttpHandler.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/OauthHttpHandler.java @@ -2,12 +2,15 @@ import com.google.common.base.Charsets; import com.google.common.base.Splitter; +import com.skcraft.launcher.Launcher; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import lombok.extern.java.Log; +import org.apache.commons.io.IOUtils; import java.io.IOException; +import java.io.InputStream; import java.net.InetSocketAddress; import java.util.Map; import java.util.concurrent.Executor; @@ -56,7 +59,14 @@ public void handle(HttpExchange httpExchange) throws IOException { OauthHttpHandler.this.notifyAll(); } - byte[] response = "OK: you can close the browser now".getBytes(Charsets.UTF_8); + byte[] response; + InputStream is = Launcher.class.getResourceAsStream("login.html"); + if (is != null) { + response = IOUtils.toByteArray(is); + } else { + response = "Unable to fetch resource login.html".getBytes(Charsets.UTF_8); + } + httpExchange.sendResponseHeaders(200, response.length); httpExchange.getResponseBody().write(response); httpExchange.getResponseBody().flush(); diff --git a/launcher/src/main/resources/com/skcraft/launcher/login.html b/launcher/src/main/resources/com/skcraft/launcher/login.html new file mode 100644 index 000000000..e0663e499 --- /dev/null +++ b/launcher/src/main/resources/com/skcraft/launcher/login.html @@ -0,0 +1 @@ +

OK: you can close the browser now

From 8dfb0490e3e01558fa75e99d707c7849d386b4dc Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Tue, 17 Jan 2023 11:03:31 +0000 Subject: [PATCH 28/45] Migrate HTTP URLs to HTTPS Fixes resource downloads --- .../resources/com/skcraft/launcher/launcher.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/src/main/resources/com/skcraft/launcher/launcher.properties b/launcher/src/main/resources/com/skcraft/launcher/launcher.properties index bfe5a72d4..1ff0c13cd 100644 --- a/launcher/src/main/resources/com/skcraft/launcher/launcher.properties +++ b/launcher/src/main/resources/com/skcraft/launcher/launcher.properties @@ -15,12 +15,12 @@ offlinePlayerName=Player # Only change these if you know what you're doing. versionManifestUrl=https://launchermeta.mojang.com/mc/game/version_manifest.json librariesSource=https://libraries.minecraft.net/ -assetsSource=http://resources.download.minecraft.net/ +assetsSource=https://resources.download.minecraft.net/ yggdrasilAuthUrl=https://authserver.mojang.com/authenticate microsoftClientId=d18bb4d8-a27f-4451-a87f-fe6de4436813 resetPasswordUrl=https://minecraft.net/resetpassword # You MUST change these from the defaults. These URLs are provides as examples only. -newsUrl=http://update.skcraft.com/template/news.html?version=%s -packageListUrl=http://update.skcraft.com/template/packages.json?key=%s -selfUpdateUrl=http://update.skcraft.com/template/launcher/latest.json +newsUrl=https://update.skcraft.com/template/news.html?version=%s +packageListUrl=https://update.skcraft.com/template/packages.json?key=%s +selfUpdateUrl=https://update.skcraft.com/template/launcher/latest.json From 60030695b38d58dd7bdfcf3aa166d5dcb5f740e3 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Thu, 23 Feb 2023 23:56:48 +0000 Subject: [PATCH 29/45] Fix update manager not displaying self-update errors --- .../src/main/java/com/skcraft/launcher/Launcher.java | 9 ++++++--- .../java/com/skcraft/launcher/dialog/LauncherFrame.java | 6 +++--- .../java/com/skcraft/launcher/update/UpdateManager.java | 6 ++++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/Launcher.java b/launcher/src/main/java/com/skcraft/launcher/Launcher.java index 962f64f8a..baef3da7e 100644 --- a/launcher/src/main/java/com/skcraft/launcher/Launcher.java +++ b/launcher/src/main/java/com/skcraft/launcher/Launcher.java @@ -105,7 +105,7 @@ public void run() { } }); - updateManager.checkForUpdate(); + updateManager.checkForUpdate(null); } /** @@ -401,8 +401,11 @@ public URL propUrl(String key, String... args) { /** * Show the launcher. */ - public void showLauncherWindow() { - mainWindowSupplier.get().setVisible(true); + public Window showLauncherWindow() { + Window window = mainWindowSupplier.get(); + window.setVisible(true); + + return window; } /** diff --git a/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java b/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java index 664afcdf7..497d1aadf 100644 --- a/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java +++ b/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java @@ -132,7 +132,7 @@ public void tableChanged(TableModelEvent e) { @Override public void actionPerformed(ActionEvent e) { loadInstances(); - launcher.getUpdateManager().checkForUpdate(); + launcher.getUpdateManager().checkForUpdate(LauncherFrame.this); webView.browse(launcher.getNewsURL(), false); } }); @@ -394,8 +394,8 @@ public void gameStarted() { @Override public void gameClosed() { - launcher.showLauncherWindow(); - launcher.getUpdateManager().checkForUpdate(); + Window newLauncherWindow = launcher.showLauncherWindow(); + launcher.getUpdateManager().checkForUpdate(newLauncherWindow); } } diff --git a/launcher/src/main/java/com/skcraft/launcher/update/UpdateManager.java b/launcher/src/main/java/com/skcraft/launcher/update/UpdateManager.java index 1d6ee2071..e24e8f370 100644 --- a/launcher/src/main/java/com/skcraft/launcher/update/UpdateManager.java +++ b/launcher/src/main/java/com/skcraft/launcher/update/UpdateManager.java @@ -50,7 +50,7 @@ public boolean getPendingUpdate() { return pendingUpdate != null; } - public void checkForUpdate() { + public void checkForUpdate(final Window window) { ListenableFuture future = launcher.getExecutor().submit(new UpdateChecker(launcher)); Futures.addCallback(future, new FutureCallback() { @@ -63,9 +63,11 @@ public void onSuccess(LatestVersionInfo result) { @Override public void onFailure(Throwable t) { - + // Error handler attached below. } }, SwingExecutor.INSTANCE); + + SwingHelper.addErrorDialogCallback(window, future); } public void performUpdate(final Window window) { From 31a13115fb0d9ef240e04b657f82b0f5e96f131a Mon Sep 17 00:00:00 2001 From: DaPorkchop_ Date: Fri, 4 Aug 2023 17:58:50 +0200 Subject: [PATCH 30/45] copy logging config from loader version manifest --- .../builder/loaders/ModernForgeLoaderProcessor.java | 6 ++++++ .../src/main/java/com/skcraft/launcher/launch/Runner.java | 2 +- .../java/com/skcraft/launcher/model/loader/VersionInfo.java | 2 ++ .../main/java/com/skcraft/launcher/update/BaseUpdater.java | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java index b21b63f61..fca72a922 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java @@ -73,6 +73,12 @@ public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapp } } + // Copy logging config + SidedData loggingConfig = info.getLogging(); + if (loggingConfig != null) { + version.setLogging(loggingConfig); + } + // Copy main class String mainClass = info.getMainClass(); if (mainClass != null) { diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java b/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java index abbee20bf..87c0b13b1 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java @@ -307,7 +307,7 @@ private void addJvmArgs() throws IOException, LauncherException { } } - if (versionManifest.getLogging() != null) { + if (versionManifest.getLogging() != null && versionManifest.getLogging().getClient() != null) { log.info("Logging config present, log4j2 bug likely mitigated"); VersionManifest.LoggingConfig config = versionManifest.getLogging().getClient(); diff --git a/launcher/src/main/java/com/skcraft/launcher/model/loader/VersionInfo.java b/launcher/src/main/java/com/skcraft/launcher/model/loader/VersionInfo.java index 6b52672a6..ecc1ba8cd 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/loader/VersionInfo.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/loader/VersionInfo.java @@ -12,6 +12,7 @@ import com.skcraft.launcher.model.minecraft.GameArgument; import com.skcraft.launcher.model.minecraft.Library; import com.skcraft.launcher.model.minecraft.MinecraftArguments; +import com.skcraft.launcher.model.minecraft.VersionManifest; import lombok.Data; import java.util.List; @@ -23,6 +24,7 @@ public class VersionInfo { private MinecraftArguments arguments; private String mainClass; private List libraries; + private SidedData logging; @JsonIgnore private transient boolean overridingArguments; diff --git a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java index e447ef031..514550592 100644 --- a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java +++ b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java @@ -282,7 +282,7 @@ protected void installLibraries(@NonNull Installer installer, } // Use our custom logging config depending on what the manifest specifies - if (versionManifest.getLogging() != null) { + if (versionManifest.getLogging() != null && versionManifest.getLogging().getClient() != null) { VersionManifest.LoggingConfig config = versionManifest.getLogging().getClient(); VersionManifest.Artifact file = config.getFile(); From 5668e567a1a3686a69073f86b1c3c7d1ca8a2ce3 Mon Sep 17 00:00:00 2001 From: DaPorkchop_ Date: Fri, 4 Aug 2023 18:00:51 +0200 Subject: [PATCH 31/45] move vanilla jar to the end of the classpath this emulates the behavior of the vanilla launcher. it's important because if the vanilla jar is first, Log4j will always auto-detect the vanilla log4j.xml instead of Forge's. --- .../src/main/java/com/skcraft/launcher/launch/Runner.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java b/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java index 87c0b13b1..0278a5f61 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java @@ -140,7 +140,6 @@ public Process call() throws Exception { } progress = new DefaultProgress(0.9, SharedLocale.tr("runner.collectingArgs")); - builder.classPath(getJarPath()); builder.setMainClass(versionManifest.getMainClass()); addWindowArgs(); @@ -232,6 +231,9 @@ private void addLibraries() throws LauncherException { tr("runner.missingLibrary", instance.getTitle(), library.getName())); } } + + // The official launcher puts the vanilla jar at the end of the classpath, we'll do the same + builder.classPath(getJarPath()); } /** From 9428dbbe7b12e88fbdceb5e02410794ed5464da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ch=2E=20K=C3=B6nig?= Date: Wed, 13 Sep 2023 19:48:41 +0200 Subject: [PATCH 32/45] Linux XDG folder support --- .../src/main/java/com/skcraft/launcher/Bootstrap.java | 7 +++++++ .../resources/com/skcraft/launcher/bootstrap.properties | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/launcher-bootstrap/src/main/java/com/skcraft/launcher/Bootstrap.java b/launcher-bootstrap/src/main/java/com/skcraft/launcher/Bootstrap.java index 463245efc..fa216fd8f 100644 --- a/launcher-bootstrap/src/main/java/com/skcraft/launcher/Bootstrap.java +++ b/launcher-bootstrap/src/main/java/com/skcraft/launcher/Bootstrap.java @@ -194,6 +194,13 @@ private File getUserLauncherDir() { String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("win")) { return new File(getFileChooseDefaultDir(), getProperties().getProperty("homeFolderWindows")); + } else if (osName.contains("linux")) { + String xdgDataHome = System.getenv("XDG_DATA_HOME"); + if (xdgDataHome == null) { + xdgDataHome = System.getProperty("user.home") + "/.local/share"; + } + + return new File(xdgDataHome, getProperties().getProperty("homeFolderLinux")); } else { return new File(System.getProperty("user.home"), getProperties().getProperty("homeFolder")); } diff --git a/launcher-bootstrap/src/main/resources/com/skcraft/launcher/bootstrap.properties b/launcher-bootstrap/src/main/resources/com/skcraft/launcher/bootstrap.properties index 8609369f7..678f61648 100644 --- a/launcher-bootstrap/src/main/resources/com/skcraft/launcher/bootstrap.properties +++ b/launcher-bootstrap/src/main/resources/com/skcraft/launcher/bootstrap.properties @@ -5,6 +5,7 @@ # homeFolderWindows=Example Launcher +homeFolderLinux=example_launcher homeFolder=.examplelauncher launcherClass=com.skcraft.launcher.Launcher -latestUrl=http://update.skcraft.com/quark/launcher/latest.json \ No newline at end of file +latestUrl=http://update.skcraft.com/quark/launcher/latest.json From 5712eb1dfba2f4692fe459f39ed2a1bbee9847cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ch=2E=20K=C3=B6nig?= Date: Wed, 20 Sep 2023 10:12:17 +0200 Subject: [PATCH 33/45] rewritten xdg folder fetcher. tries old dotfolder first --- .../main/java/com/skcraft/launcher/Bootstrap.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/launcher-bootstrap/src/main/java/com/skcraft/launcher/Bootstrap.java b/launcher-bootstrap/src/main/java/com/skcraft/launcher/Bootstrap.java index fa216fd8f..7f1890594 100644 --- a/launcher-bootstrap/src/main/java/com/skcraft/launcher/Bootstrap.java +++ b/launcher-bootstrap/src/main/java/com/skcraft/launcher/Bootstrap.java @@ -194,16 +194,21 @@ private File getUserLauncherDir() { String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("win")) { return new File(getFileChooseDefaultDir(), getProperties().getProperty("homeFolderWindows")); - } else if (osName.contains("linux")) { + } + + File dotFolder = new File(System.getProperty("user.home"), getProperties().getProperty("homeFolder")); + String xdgFolderName = getProperties().getProperty("homeFolderLinux"); + + if (osName.contains("linux") && !dotFolder.exists() && !xdgFolderName.isEmpty()) { String xdgDataHome = System.getenv("XDG_DATA_HOME"); - if (xdgDataHome == null) { + if (xdgDataHome.isEmpty()) { xdgDataHome = System.getProperty("user.home") + "/.local/share"; } - return new File(xdgDataHome, getProperties().getProperty("homeFolderLinux")); - } else { - return new File(System.getProperty("user.home"), getProperties().getProperty("homeFolder")); + return new File(xdgDataHome, xdgFolderName); } + + return dotFolder; } private static boolean isPortableMode() { From 11808457fef3f3e351cdc544b1db76f721822957 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Tue, 2 Jan 2024 20:22:23 +0000 Subject: [PATCH 34/45] Fix launcher trying to download processor outputs Fix for forge 1.20.4; the generated client jar is specified as a library because it goes on the classpath now. --- .../loaders/ModernForgeLoaderProcessor.java | 16 ++++++++++++++++ .../launcher/model/minecraft/Library.java | 4 +++- .../com/skcraft/launcher/update/BaseUpdater.java | 2 ++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java index b21b63f61..b59201b3c 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java @@ -150,6 +150,22 @@ public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapp // Add loader manifest to the map manifest.getLoaders().put(loaderName, new LoaderManifest(profile.getLibraries(), profile.getData(), extraFiles)); + // Find name of final patched library and mark it as excluded from download + // TODO: we should generalize this to all process outputs, really + SidedData finalJars = profile.getData().get("PATCHED"); + if (finalJars != null) { + String libraryName = finalJars.getClient(); + libraryName = libraryName.substring(1, libraryName.length() - 1); + + for (Library lib : result.getLoaderLibraries()) { + if (lib.getName().equals(libraryName)) { + lib.setGenerated(true); + log.info(String.format("Setting generated flag on library '%s'", lib.getName())); + break; + } + } + } + // Add processors manifest.getTasks().addAll(profile.toProcessorEntries(loaderName)); } diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java index f6cd2d8c8..2fa1c35d3 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.collect.Lists; @@ -33,7 +34,8 @@ public class Library { private String comment; // Custom - private boolean locallyAvailable; + @JsonInclude(value = JsonInclude.Include.NON_DEFAULT) + private boolean generated; public boolean matches(Environment environment) { boolean allow = false; diff --git a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java index e447ef031..ea6dff06a 100644 --- a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java +++ b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java @@ -249,6 +249,8 @@ protected void installLibraries(@NonNull Installer installer, } for (Library library : allLibraries) { + if (library.isGenerated()) continue; // Skip generated libraries. + if (library.matches(environment)) { checkInterrupted(); From b5fe175650b14dac472bb84a95d15613078a84c0 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Tue, 2 Jan 2024 20:58:51 +0000 Subject: [PATCH 35/45] Add support for NeoForge --- .../launcher/builder/PackageBuilder.java | 2 +- .../loaders/ModernForgeLoaderProcessor.java | 2 +- .../launcher/model/loader/LoaderManifest.java | 2 +- .../launcher/model/minecraft/Library.java | 20 +++++++++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java index 705735c5b..9981a1763 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java @@ -164,7 +164,7 @@ private void processLoader(LinkedHashSet loaderLibraries, File file, Fi if (basicProfile.isLegacy()) { processor = new OldForgeLoaderProcessor(); - } else if (basicProfile.getProfile().equalsIgnoreCase("forge")) { + } else { processor = new ModernForgeLoaderProcessor(); } } else if (BuilderUtils.getZipEntry(jarFile, "fabric-installer.json") != null) { diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java index b59201b3c..fd599bfdc 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/loaders/ModernForgeLoaderProcessor.java @@ -158,7 +158,7 @@ public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapp libraryName = libraryName.substring(1, libraryName.length() - 1); for (Library lib : result.getLoaderLibraries()) { - if (lib.getName().equals(libraryName)) { + if (lib.matches(libraryName)) { lib.setGenerated(true); log.info(String.format("Setting generated flag on library '%s'", lib.getName())); break; diff --git a/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderManifest.java b/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderManifest.java index c1b567c70..6d6cb7aa8 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderManifest.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderManifest.java @@ -19,7 +19,7 @@ public class LoaderManifest { public Library findLibrary(String name) { for (Library library : getLibraries()) { - if (library.getName().equals(name)) { + if (library.matches(name)) { return library; } } diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java index 2fa1c35d3..3945c104b 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java @@ -203,6 +203,12 @@ public void setUrl(String url) { } public void setName(String name) { + int classifierPos = name.indexOf("@"); + if (classifierPos != -1) { + // Take off classifiers + name = name.substring(0, classifierPos); + } + this.name = name; // [DEEP SIGH] @@ -228,6 +234,20 @@ public void setServerreq(boolean value) { } } + /** + * Classifier-independent library name check + * @param mavenName Maven name of a library, possibly with a classifier + * @return True if this library is named 'mavenName'. + */ + public boolean matches(String mavenName) { + int classifierPos = mavenName.indexOf('@'); + if (classifierPos != -1) { + mavenName = mavenName.substring(0, classifierPos); + } + + return this.name.equals(mavenName); + } + public static String mavenNameToPath(String mavenName) { List split = Splitter.on(':').splitToList(mavenName); int size = split.size(); From 5eca6c2b434a686ea3a4960d92011193f82825c9 Mon Sep 17 00:00:00 2001 From: Magi1053 Date: Fri, 29 Mar 2024 23:11:23 -0500 Subject: [PATCH 36/45] Visually improve oauth login response page --- .../auth/microsoft/OauthHttpHandler.java | 10 ++++++++ .../resources/com/skcraft/launcher/login.html | 25 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/OauthHttpHandler.java b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/OauthHttpHandler.java index 7e0ea5943..0eddbb446 100644 --- a/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/OauthHttpHandler.java +++ b/launcher/src/main/java/com/skcraft/launcher/auth/microsoft/OauthHttpHandler.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.InetSocketAddress; +import java.util.Base64; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -67,6 +68,15 @@ public void handle(HttpExchange httpExchange) throws IOException { response = "Unable to fetch resource login.html".getBytes(Charsets.UTF_8); } + InputStream iconStream = Launcher.class.getResourceAsStream("icon.png"); + if (iconStream != null) { + byte[] iconBytes = IOUtils.toByteArray(iconStream); + String encodedIcon = Base64.getEncoder().encodeToString(iconBytes); + response = String.format(new String(response), encodedIcon).getBytes(); + } else { + log.warning("Unable to fetch resource icon.png"); + } + httpExchange.sendResponseHeaders(200, response.length); httpExchange.getResponseBody().write(response); httpExchange.getResponseBody().flush(); diff --git a/launcher/src/main/resources/com/skcraft/launcher/login.html b/launcher/src/main/resources/com/skcraft/launcher/login.html index e0663e499..560fb0ee7 100644 --- a/launcher/src/main/resources/com/skcraft/launcher/login.html +++ b/launcher/src/main/resources/com/skcraft/launcher/login.html @@ -1 +1,24 @@ -

OK: you can close the browser now

+ + + + You can now close your browser + + + +
+ icon.png +

You can now close your browser

+
+ + From d197bc80cc4c8a0610848258e13c02a00f7d4fa0 Mon Sep 17 00:00:00 2001 From: Henry Le Grys Date: Mon, 15 Apr 2024 23:19:10 +0100 Subject: [PATCH 37/45] Fix maven for 'insubstantial' library --- launcher-fancy/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher-fancy/build.gradle b/launcher-fancy/build.gradle index e387be495..22af7053d 100644 --- a/launcher-fancy/build.gradle +++ b/launcher-fancy/build.gradle @@ -10,8 +10,8 @@ application { repositories { maven { - name = 'obw maven' - url = 'https://maven.offbeatwit.ch/repository/snapshots' + name = 'bbkr.space maven' + url = 'https://server.bbkr.space/artifactory/libs-snapshot' } } From 9147cb2ad0086b29aa57a00d3ba7fd5a3a81be30 Mon Sep 17 00:00:00 2001 From: Magi1053 Date: Wed, 1 May 2024 22:30:35 -0500 Subject: [PATCH 38/45] Add icon to favicon --- launcher/src/main/resources/com/skcraft/launcher/login.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/src/main/resources/com/skcraft/launcher/login.html b/launcher/src/main/resources/com/skcraft/launcher/login.html index 560fb0ee7..22c54ff7f 100644 --- a/launcher/src/main/resources/com/skcraft/launcher/login.html +++ b/launcher/src/main/resources/com/skcraft/launcher/login.html @@ -2,6 +2,7 @@ You can now close your browser +