From 97a73acac5bfcd40d1c50fcbb9c19b07643d9e2e Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:20:40 -0700 Subject: [PATCH 01/30] stage0/ml9: create mixin bootstrap --- stage0/modlauncher9/build.gradle | 10 +++ .../stage0/EssentialStage0MixinPlugin.java | 80 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 stage0/modlauncher9/src/main/java/gg/essential/loader/stage0/EssentialStage0MixinPlugin.java diff --git a/stage0/modlauncher9/build.gradle b/stage0/modlauncher9/build.gradle index e981db8..6f3a469 100644 --- a/stage0/modlauncher9/build.gradle +++ b/stage0/modlauncher9/build.gradle @@ -8,4 +8,14 @@ dependencies { compileOnly("cpw.mods:securejarhandler:0.9.50") compileOnly("net.sf.jopt-simple:jopt-simple:5.0.4") compileOnly("org.jetbrains:annotations:21.0.1") + // as of forge 37.1 for MC 1.17.1, mixin is shipped with forge + // https://github.com/MinecraftForge/MinecraftForge/commit/c8d3ad1d1c977513b75e6aa3dd81c6ed9463bcae + compileOnly("org.spongepowered:mixin:0.8.5") } + +jar { + manifest { + // this is removed when people include the loader however better to have it than not + attributes("MixinConfigs": "gg.essential.loader.stage0.EssentialStage0MixinPlugin") + } +} \ No newline at end of file diff --git a/stage0/modlauncher9/src/main/java/gg/essential/loader/stage0/EssentialStage0MixinPlugin.java b/stage0/modlauncher9/src/main/java/gg/essential/loader/stage0/EssentialStage0MixinPlugin.java new file mode 100644 index 0000000..17a01f3 --- /dev/null +++ b/stage0/modlauncher9/src/main/java/gg/essential/loader/stage0/EssentialStage0MixinPlugin.java @@ -0,0 +1,80 @@ +package gg.essential.loader.stage0; + +import cpw.mods.modlauncher.Launcher; +import cpw.mods.modlauncher.api.IEnvironment; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Set; + +import static gg.essential.loader.stage0.EssentialLoader.STAGE1_PKG; + +@SuppressWarnings("unused") +public class EssentialStage0MixinPlugin implements IMixinConfigPlugin { + private static final String STAGE1_CLS = STAGE1_PKG + "EssentialMixinPluginLoader"; + @Override + public void onLoad(String mixinPackage) { + loadStage1OrThrow(this); + } + + private static void loadStage1OrThrow(Object stage0) { + try { + loadStage1(stage0); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void loadStage1(Object stage0) throws Exception { + Path gameDir = Launcher.INSTANCE.environment() + .getProperty(IEnvironment.Keys.GAMEDIR.get()) + .orElseGet(() -> Paths.get(".")); + + final EssentialLoader loader = new EssentialLoader("modlauncher"); // using same variant as the transformation service + final Path stage1File = loader.loadStage1File(gameDir); + final URL stage1Url = stage1File.toUri().toURL(); + + // Create a class loader with which to load stage1 + URLClassLoader classLoader = new URLClassLoader(new URL[]{ stage1Url }, stage0.getClass().getClassLoader()); + + Class.forName(STAGE1_CLS, true, classLoader) + .getConstructor() + .newInstance(); + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + return false; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } +} From aef0cebb284339f893ade2549d0dd4fc28d9f3ab Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:14:00 -0700 Subject: [PATCH 02/30] stage0/ml9: refactor transformation service file to container only --- .../services/cpw.mods.modlauncher.api.ITransformationService | 0 .../services/cpw.mods.modlauncher.api.ITransformationService | 1 - 2 files changed, 1 deletion(-) rename {stage0/modlauncher8/src/main/resources/META-INF => container/modlauncher9/resources}/services/cpw.mods.modlauncher.api.ITransformationService (100%) delete mode 100644 stage0/modlauncher9/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService diff --git a/stage0/modlauncher8/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/container/modlauncher9/resources/services/cpw.mods.modlauncher.api.ITransformationService similarity index 100% rename from stage0/modlauncher8/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService rename to container/modlauncher9/resources/services/cpw.mods.modlauncher.api.ITransformationService diff --git a/stage0/modlauncher9/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/stage0/modlauncher9/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService deleted file mode 100644 index e32f3f4..0000000 --- a/stage0/modlauncher9/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService +++ /dev/null @@ -1 +0,0 @@ -gg.essential.loader.stage0.EssentialTransformationService From 6410897f5689b1b3de0cc4886aadddb4d51b804c Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:15:30 -0700 Subject: [PATCH 03/30] stage1/ml9: create mixin bootstrap --- .../stage1/EssentialMixinPluginLoader.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java diff --git a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java new file mode 100644 index 0000000..04b99d1 --- /dev/null +++ b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java @@ -0,0 +1,37 @@ +package gg.essential.loader.stage1; + +import cpw.mods.modlauncher.Launcher; +import cpw.mods.modlauncher.api.IEnvironment; +import cpw.mods.modlauncher.api.TypesafeMap; +import net.minecraftforge.fml.loading.FMLLoader; + +import java.nio.file.Path; +import java.nio.file.Paths; + +@SuppressWarnings("unused") +public class EssentialMixinPluginLoader { + private static final String KEY_LOADED = "gg.essential.loader.stage1.loaded"; + + public EssentialMixinPluginLoader() throws Exception { + // Check if another stage1 loader has already loaded stage2 (we do not want to load it twice) + final TypesafeMap blackboard = Launcher.INSTANCE.blackboard(); + final TypesafeMap.Key LOADED = + TypesafeMap.Key.getOrCreate(blackboard, KEY_LOADED, Object.class); + if (blackboard.get(LOADED).isPresent()) { + return; + } + // We are doing it + blackboard.computeIfAbsent(LOADED, __ -> this); + + final Path gameDir = Launcher.INSTANCE.environment() + .getProperty(IEnvironment.Keys.GAMEDIR.get()) + .orElse(Paths.get(".")); + + EssentialLoader loader = EssentialLoader.getInstance("modlauncher", "forge_" + FMLLoader.versionInfo().mcVersion()); + loader.load(gameDir); + + loader.getStage2().getClass() + .getMethod("loadFromMixin", Path.class) + .invoke(loader.getStage2(), gameDir); + } +} From eac3a3f401ac2135bcd0d8b304a1babe8777705d Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:22:26 -0700 Subject: [PATCH 04/30] stage2/ml9: create mixin bootstrap --- .../loader/stage2/DedicatedJarLoader.java | 65 +++++++++++++++ .../loader/stage2/EssentialLoader.java | 19 +++++ .../gg/essential/loader/stage2/RestartUI.java | 81 +++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java create mode 100644 stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/RestartUI.java diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java new file mode 100644 index 0000000..38b3c5a --- /dev/null +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java @@ -0,0 +1,65 @@ +package gg.essential.loader.stage2; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; + +public class DedicatedJarLoader { + private static final String BASE_URL = System.getProperty( + "essential.download.url", + System.getenv().getOrDefault("ESSENTIAL_DOWNLOAD_URL", "https://api.essential.gg/mods") + ); + private static final String VERSION_URL = BASE_URL + "/v1/essential:essential-pinned/versions/stable/platforms/%s"; + private static final String DOWNLOAD_URL = VERSION_URL + "/download"; + + protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gameVersion) throws IOException { + final JsonObject meta = getEssentialDownloadMeta(gameVersion); + final URL url = new URL(meta.get("url").getAsString()); + final URLConnection connection = url.openConnection(); + + ui.setDownloadSize(connection.getContentLength()); + + final String essentialVersion = getEssentialVersionMeta(gameVersion).get("version").getAsString(); + final Path target = modsDir.resolve(String.format("Essential %s (%s).jar", gameVersion, essentialVersion)); + + try ( + final InputStream in = connection.getInputStream(); + final OutputStream out = Files.newOutputStream(target); + ) { + + final byte[] buffer = new byte[1024]; + int totalRead = 0; + int read; + while ((read = in.read(buffer)) != -1) { + out.write(buffer, 0, read); + totalRead += read; + ui.setDownloaded(totalRead); + } + } + } + + private static JsonObject getEssentialMeta(URL url) throws IOException { + String response; + try (final InputStream in = url.openStream()) { + response = new String(in.readAllBytes()); + } + JsonElement json = new JsonParser().parse(response); + return json.getAsJsonObject(); + } + + private static JsonObject getEssentialVersionMeta(String gameVersion) throws IOException { + return getEssentialMeta(new URL(String.format(VERSION_URL, gameVersion))); + } + + private static JsonObject getEssentialDownloadMeta(String gameVersion) throws IOException { + return getEssentialMeta(new URL(String.format(DOWNLOAD_URL, gameVersion))); + } +} diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java index 4be0bb8..079a8e5 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java @@ -1,7 +1,10 @@ package gg.essential.loader.stage2; import cpw.mods.modlauncher.api.ITransformationService; +import gg.essential.loader.stage2.jvm.ForkedJvmLoaderSwingUI; +import net.minecraftforge.fml.loading.FMLLoader; +import java.io.IOException; import java.nio.file.Path; /** @@ -26,4 +29,20 @@ public ITransformationService getTransformationService() { public void load() { // delayed until ModLauncher exposes the MC version } + + @SuppressWarnings("unused") // called via reflection from stage1 + public void loadFromMixin(Path gameDir) throws IOException { + final Path modsDir = gameDir.resolve("mods"); + LoaderUI ui = LoaderUI.all( + new LoaderLoggingUI().updatesEveryMillis(1000), + new ForkedJvmLoaderSwingUI().updatesEveryMillis(1000 / 60) + ); + ui.start(); + DedicatedJarLoader.downloadDedicatedJar(ui, modsDir, "forge_" + FMLLoader.versionInfo().mcVersion()); + ui.complete(); + RestartUI restartUI = new RestartUI("Restart Required!", "One of the mods you have installed requires Essential. To complete the installation process, please restart."); + restartUI.show(); + restartUI.waitForClose(); + System.exit(0); + } } diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/RestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/RestartUI.java new file mode 100644 index 0000000..1cb9102 --- /dev/null +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/RestartUI.java @@ -0,0 +1,81 @@ +package gg.essential.loader.stage2; + +import gg.essential.loader.stage2.components.EssentialStyle; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import static gg.essential.loader.stage2.components.ButtonShadowBorder.X_SHADOW; +import static gg.essential.loader.stage2.components.ButtonShadowBorder.Y_SHADOW; + +public class RestartUI implements EssentialStyle { + private final CompletableFuture closedFuture = new CompletableFuture<>(); + + private final JFrame frame = makeFrame(it -> closedFuture.complete(null)); + + private final String title; + private final String description; + + public RestartUI(String title, String description) { + this.title = title; + this.description = description; + } + + public void show() { + final List htmlLabels = new ArrayList<>(); + + final JPanel content = makeContent(frame); + content.setBorder(new EmptyBorder(0, 60 - X_SHADOW, 0, 60 - X_SHADOW)); + content.add(Box.createHorizontalStrut(CONTENT_WIDTH)); + + htmlLabels.add(makeTitle(content, html(centered(title)))); + + final JLabel explanation = new JLabel(html(centered(description)), SwingConstants.CENTER); + explanation.setMaximumSize(new Dimension(CONTENT_WIDTH, Integer.MAX_VALUE)); + explanation.setForeground(COLOR_FOREGROUND); + explanation.setAlignmentX(Container.CENTER_ALIGNMENT); + if (Fonts.medium != null) { + explanation.setFont(Fonts.medium.deriveFont(16F)); + } + content.add(explanation); + htmlLabels.add(explanation); + + content.add(Box.createVerticalStrut(32 - Y_SHADOW)); + + final JPanel buttons = new JPanel(); + buttons.setOpaque(false); + buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS)); + buttons.add(makeButton("Restart", COLOR_PRIMARY_BUTTON, COLOR_BUTTON_HOVER, () -> closedFuture.complete(true))); + content.add(buttons); + + content.add(Box.createVerticalStrut(32 - Y_SHADOW)); + + frame.pack(); + + htmlLabels.forEach(this::fixJLabelHeight); + frame.pack(); + + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public Boolean waitForClose() { + Boolean verdict = closedFuture.join(); + close(); + return verdict; + } + + public void close() { + frame.dispose(); + } + + public static void main(String[] args) { + RestartUI ui = new RestartUI("Restart required!", "A restart is required for something."); + ui.show(); + System.out.println(ui.waitForClose()); + } +} From 329bbd8421062cbbc304266a3b0da04e2524cfa9 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:06:45 -0700 Subject: [PATCH 05/30] stage1/ml9: make transformation service path compatible with mixin bootstrap path --- .../loader/stage1/EssentialTransformationServiceBase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java b/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java index 17936ba..330c8e5 100644 --- a/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java +++ b/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java @@ -28,10 +28,10 @@ public EssentialTransformationServiceBase( ) throws Exception { super(stage1 -> newFallbackService.apply(findUniqueId(stage0))); - // Check if another transformation service has already loaded stage2 (we do not want to load it twice) + // Check if another stage 1 loader has already loaded stage2 (we do not want to load it twice) final TypesafeMap blackboard = Launcher.INSTANCE.blackboard(); final TypesafeMap.Key LOADED = - TypesafeMap.Key.getOrCreate(blackboard, KEY_LOADED, ITransformationService.class); + TypesafeMap.Key.getOrCreate(blackboard, KEY_LOADED, Object.class); if (blackboard.get(LOADED).isPresent()) { return; } From 1e7be5b82bf38d59684f3e028d6783b48d09dac3 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 10:30:31 -0700 Subject: [PATCH 06/30] stage2/ml9: adjust restart message to be more clear --- .../main/java/gg/essential/loader/stage2/EssentialLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java index 079a8e5..77a3dd3 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java @@ -40,7 +40,7 @@ public void loadFromMixin(Path gameDir) throws IOException { ui.start(); DedicatedJarLoader.downloadDedicatedJar(ui, modsDir, "forge_" + FMLLoader.versionInfo().mcVersion()); ui.complete(); - RestartUI restartUI = new RestartUI("Restart Required!", "One of the mods you have installed requires Essential. To complete the installation process, please restart."); + RestartUI restartUI = new RestartUI("Restart Required!", "One of the mods you have installed requires Essential. To complete the installation process, please restart minecraft."); restartUI.show(); restartUI.waitForClose(); System.exit(0); From a572fdfe0dced06c27fab2a0cf6967ab2c6db648 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 10:53:04 -0700 Subject: [PATCH 07/30] stage2/ml9: change to downloading to a temp file and moving it on completion --- .../essential/loader/stage2/DedicatedJarLoader.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java index 38b3c5a..0b0d649 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java @@ -3,6 +3,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.IOException; import java.io.InputStream; @@ -12,7 +14,10 @@ import java.nio.file.Files; import java.nio.file.Path; +import static java.nio.file.StandardCopyOption.ATOMIC_MOVE; + public class DedicatedJarLoader { + private static final Logger LOGGER = LogManager.getLogger(DedicatedJarLoader.class); private static final String BASE_URL = System.getProperty( "essential.download.url", System.getenv().getOrDefault("ESSENTIAL_DOWNLOAD_URL", "https://api.essential.gg/mods") @@ -29,12 +34,12 @@ protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gam final String essentialVersion = getEssentialVersionMeta(gameVersion).get("version").getAsString(); final Path target = modsDir.resolve(String.format("Essential %s (%s).jar", gameVersion, essentialVersion)); + final Path tempFile = Files.createTempFile("Dedicated Essential jar", ""); try ( final InputStream in = connection.getInputStream(); - final OutputStream out = Files.newOutputStream(target); + final OutputStream out = Files.newOutputStream(tempFile); ) { - final byte[] buffer = new byte[1024]; int totalRead = 0; int read; @@ -43,6 +48,8 @@ protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gam totalRead += read; ui.setDownloaded(totalRead); } + + Files.move(tempFile, target, ATOMIC_MOVE); } } From 72015f4554b94b7e3c1ce8e6147fd720bde8ab2b Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 10:57:35 -0700 Subject: [PATCH 08/30] Revert "stage0/ml9: refactor transformation service file to container only" This reverts commit aef0cebb284339f893ade2549d0dd4fc28d9f3ab. --- .../services/cpw.mods.modlauncher.api.ITransformationService | 0 .../services/cpw.mods.modlauncher.api.ITransformationService | 1 + 2 files changed, 1 insertion(+) rename {container/modlauncher9/resources => stage0/modlauncher8/src/main/resources/META-INF}/services/cpw.mods.modlauncher.api.ITransformationService (100%) create mode 100644 stage0/modlauncher9/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService diff --git a/container/modlauncher9/resources/services/cpw.mods.modlauncher.api.ITransformationService b/stage0/modlauncher8/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService similarity index 100% rename from container/modlauncher9/resources/services/cpw.mods.modlauncher.api.ITransformationService rename to stage0/modlauncher8/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService diff --git a/stage0/modlauncher9/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/stage0/modlauncher9/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService new file mode 100644 index 0000000..e32f3f4 --- /dev/null +++ b/stage0/modlauncher9/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService @@ -0,0 +1 @@ +gg.essential.loader.stage0.EssentialTransformationService From 472f1c952daf830cae5c10c4aba71ad5aff8623c Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:03:42 -0700 Subject: [PATCH 09/30] stage0/ml9: move load to constructor instead of `onLoad` --- .../loader/stage0/EssentialStage0MixinPlugin.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/stage0/modlauncher9/src/main/java/gg/essential/loader/stage0/EssentialStage0MixinPlugin.java b/stage0/modlauncher9/src/main/java/gg/essential/loader/stage0/EssentialStage0MixinPlugin.java index 17a01f3..d7550c6 100644 --- a/stage0/modlauncher9/src/main/java/gg/essential/loader/stage0/EssentialStage0MixinPlugin.java +++ b/stage0/modlauncher9/src/main/java/gg/essential/loader/stage0/EssentialStage0MixinPlugin.java @@ -18,17 +18,13 @@ @SuppressWarnings("unused") public class EssentialStage0MixinPlugin implements IMixinConfigPlugin { private static final String STAGE1_CLS = STAGE1_PKG + "EssentialMixinPluginLoader"; - @Override - public void onLoad(String mixinPackage) { - loadStage1OrThrow(this); + + public EssentialStage0MixinPlugin() throws Exception { + loadStage1(this); } - private static void loadStage1OrThrow(Object stage0) { - try { - loadStage1(stage0); - } catch (Exception e) { - throw new RuntimeException(e); - } + @Override + public void onLoad(String mixinPackage) { } private static void loadStage1(Object stage0) throws Exception { From 54c2da3364adec0267493ae661136ee9dd840f34 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:05:10 -0700 Subject: [PATCH 10/30] stage1/ml9: switch back to looking for `ITransformationService` --- .../stage1/EssentialTransformationServiceBase.java | 4 ++-- .../loader/stage1/EssentialMixinPluginLoader.java | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java b/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java index 330c8e5..17936ba 100644 --- a/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java +++ b/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java @@ -28,10 +28,10 @@ public EssentialTransformationServiceBase( ) throws Exception { super(stage1 -> newFallbackService.apply(findUniqueId(stage0))); - // Check if another stage 1 loader has already loaded stage2 (we do not want to load it twice) + // Check if another transformation service has already loaded stage2 (we do not want to load it twice) final TypesafeMap blackboard = Launcher.INSTANCE.blackboard(); final TypesafeMap.Key LOADED = - TypesafeMap.Key.getOrCreate(blackboard, KEY_LOADED, Object.class); + TypesafeMap.Key.getOrCreate(blackboard, KEY_LOADED, ITransformationService.class); if (blackboard.get(LOADED).isPresent()) { return; } diff --git a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java index 04b99d1..3e1af8b 100644 --- a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java +++ b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java @@ -2,6 +2,7 @@ import cpw.mods.modlauncher.Launcher; import cpw.mods.modlauncher.api.IEnvironment; +import cpw.mods.modlauncher.api.ITransformationService; import cpw.mods.modlauncher.api.TypesafeMap; import net.minecraftforge.fml.loading.FMLLoader; @@ -13,15 +14,13 @@ public class EssentialMixinPluginLoader { private static final String KEY_LOADED = "gg.essential.loader.stage1.loaded"; public EssentialMixinPluginLoader() throws Exception { - // Check if another stage1 loader has already loaded stage2 (we do not want to load it twice) + // Check if another transformation service has already loaded stage2 (we do not want to load it twice) final TypesafeMap blackboard = Launcher.INSTANCE.blackboard(); - final TypesafeMap.Key LOADED = - TypesafeMap.Key.getOrCreate(blackboard, KEY_LOADED, Object.class); + final TypesafeMap.Key LOADED = + TypesafeMap.Key.getOrCreate(blackboard, KEY_LOADED, ITransformationService.class); if (blackboard.get(LOADED).isPresent()) { return; } - // We are doing it - blackboard.computeIfAbsent(LOADED, __ -> this); final Path gameDir = Launcher.INSTANCE.environment() .getProperty(IEnvironment.Keys.GAMEDIR.get()) From 7c6a482e4f8a7ce3887405c08f25527f830b89ce Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:06:23 -0700 Subject: [PATCH 11/30] stage1/ml9: use same key for mixin path loaded --- .../loader/stage1/EssentialTransformationServiceBase.java | 2 +- .../gg/essential/loader/stage1/EssentialMixinPluginLoader.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java b/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java index 17936ba..15ae0b3 100644 --- a/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java +++ b/stage1/modlauncher/src/main/java/gg/essential/loader/stage1/EssentialTransformationServiceBase.java @@ -18,7 +18,7 @@ import java.util.stream.Collectors; public abstract class EssentialTransformationServiceBase extends DelegatingTransformationServiceBase { - private static final String KEY_LOADED = "gg.essential.loader.stage1.loaded"; + protected static final String KEY_LOADED = "gg.essential.loader.stage1.loaded"; public EssentialTransformationServiceBase( final ITransformationService stage0, diff --git a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java index 3e1af8b..35b8cf5 100644 --- a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java +++ b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java @@ -9,9 +9,10 @@ import java.nio.file.Path; import java.nio.file.Paths; +import static gg.essential.loader.stage1.EssentialTransformationServiceBase.KEY_LOADED; + @SuppressWarnings("unused") public class EssentialMixinPluginLoader { - private static final String KEY_LOADED = "gg.essential.loader.stage1.loaded"; public EssentialMixinPluginLoader() throws Exception { // Check if another transformation service has already loaded stage2 (we do not want to load it twice) From 8afb6f32ed40fe1704b4eaa015443147da37f2db Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:21:54 -0700 Subject: [PATCH 12/30] stage1/ml9: use same stage2 path as transformation service --- .../gg/essential/loader/stage1/EssentialMixinPluginLoader.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java index 35b8cf5..68c5f54 100644 --- a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java +++ b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java @@ -27,7 +27,8 @@ public EssentialMixinPluginLoader() throws Exception { .getProperty(IEnvironment.Keys.GAMEDIR.get()) .orElse(Paths.get(".")); - EssentialLoader loader = EssentialLoader.getInstance("modlauncher", "forge_" + FMLLoader.versionInfo().mcVersion()); + // variant and game version to match transformation service path + EssentialLoader loader = EssentialLoader.getInstance("modlauncher9", "forge_1.17.1"); loader.load(gameDir); loader.getStage2().getClass() From cc77ad2439e72d86a70e09b9a8005fc14840b701 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:58:17 -0700 Subject: [PATCH 13/30] stage2/ml9: handle dedicated jar loader exceptions --- .../loader/stage2/EssentialLoader.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java index 77a3dd3..941f887 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java @@ -1,8 +1,11 @@ package gg.essential.loader.stage2; import cpw.mods.modlauncher.api.ITransformationService; +import gg.essential.loader.stage2.components.ForkedRestartUI; +import gg.essential.loader.stage2.components.RestartUI; import gg.essential.loader.stage2.jvm.ForkedJvmLoaderSwingUI; import net.minecraftforge.fml.loading.FMLLoader; +import org.apache.logging.log4j.LogManager; import java.io.IOException; import java.nio.file.Path; @@ -31,18 +34,23 @@ public void load() { } @SuppressWarnings("unused") // called via reflection from stage1 - public void loadFromMixin(Path gameDir) throws IOException { + public void loadFromMixin(Path gameDir) { final Path modsDir = gameDir.resolve("mods"); LoaderUI ui = LoaderUI.all( new LoaderLoggingUI().updatesEveryMillis(1000), new ForkedJvmLoaderSwingUI().updatesEveryMillis(1000 / 60) ); ui.start(); - DedicatedJarLoader.downloadDedicatedJar(ui, modsDir, "forge_" + FMLLoader.versionInfo().mcVersion()); - ui.complete(); - RestartUI restartUI = new RestartUI("Restart Required!", "One of the mods you have installed requires Essential. To complete the installation process, please restart minecraft."); - restartUI.show(); - restartUI.waitForClose(); + try { + DedicatedJarLoader.downloadDedicatedJar(ui, modsDir, "forge_" + FMLLoader.versionInfo().mcVersion()); + } catch (IOException e) { + LogManager.getLogger().warn("Failed to download dedicated jar:", e); + } finally { + ui.complete(); + RestartUI restartUI = new RestartUI("Restart Required!", "One of the mods you have installed requires Essential. To complete the installation process, please restart minecraft."); + restartUI.show(); + restartUI.waitForClose(); + } System.exit(0); } } From 966eb040a918d5db55e6a352d507dd0ec73195b5 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:00:46 -0700 Subject: [PATCH 14/30] stage2/ml9: use forked jvm for restart ui --- .../loader/stage2/EssentialLoader.java | 2 +- .../stage2/components/ForkedRestartUI.java | 75 +++++++++++++++++++ .../stage2/{ => components}/RestartUI.java | 4 +- 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java rename stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/{ => components}/RestartUI.java (96%) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java index 941f887..6e09732 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java @@ -47,7 +47,7 @@ public void loadFromMixin(Path gameDir) { LogManager.getLogger().warn("Failed to download dedicated jar:", e); } finally { ui.complete(); - RestartUI restartUI = new RestartUI("Restart Required!", "One of the mods you have installed requires Essential. To complete the installation process, please restart minecraft."); + ForkedRestartUI restartUI = new ForkedRestartUI("Restart Required!", "One of the mods you have installed requires Essential. To complete the installation process, please restart minecraft."); restartUI.show(); restartUI.waitForClose(); } diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java new file mode 100644 index 0000000..bea4ba9 --- /dev/null +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java @@ -0,0 +1,75 @@ +package gg.essential.loader.stage2.components; + +import gg.essential.loader.stage2.jvm.ForkedJvm; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class ForkedRestartUI { + private final Logger LOGGER = LogManager.getLogger(); + private final String title; + private final String description; + private ForkedJvm jvm; + + public ForkedRestartUI(String title, String description) { + this.title = title; + this.description = description; + } + + public void show() { + try { + this.jvm = new ForkedJvm(getClass()); + + DataOutputStream out = new DataOutputStream(this.jvm.process.getOutputStream()); + out.writeUTF(title); + out.writeUTF(description); + out.flush(); + } catch (IOException e) { + LOGGER.warn("Failed to fork JVM for RestartUI:", e); + } + } + + public Boolean waitForClose() { + if (this.jvm != null) return null; + + try { + int verdict = this.jvm.process.getInputStream().read(); + return verdict == 1 ? Boolean.TRUE : verdict == 2 ? Boolean.FALSE : null; + } catch (IOException e) { + LOGGER.warn("Failed to wait for RestartUI to close:", e); + return null; + } finally { + this.jvm.close(); + this.jvm = null; + } + } + + public static void main(String[] args) throws IOException { + DataInputStream in = new DataInputStream(System.in); + + String title = in.readUTF(); + String description = in.readUTF(); + + Boolean verdict = null; + try { + RestartUI ui = new RestartUI(title, description); + ui.show(); + + verdict = ui.waitForClose(); + } catch (Throwable t) { + t.printStackTrace(); + } + + if (verdict == Boolean.TRUE) { + System.out.write(1); + } else if (verdict == Boolean.FALSE) { + System.out.write(2); + } else { + System.out.write(0); + } + System.out.flush(); + } +} diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/RestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java similarity index 96% rename from stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/RestartUI.java rename to stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java index 1cb9102..c6bff2b 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/RestartUI.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java @@ -1,6 +1,4 @@ -package gg.essential.loader.stage2; - -import gg.essential.loader.stage2.components.EssentialStyle; +package gg.essential.loader.stage2.components; import javax.swing.*; import javax.swing.border.EmptyBorder; From 567b52c63b2157b97c8df83367c9b59fbd368aab Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:01:35 -0700 Subject: [PATCH 15/30] stage2/ml9: flip game and mod version for dedicated jar --- .../java/gg/essential/loader/stage2/DedicatedJarLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java index 0b0d649..65b728e 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java @@ -33,7 +33,7 @@ protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gam ui.setDownloadSize(connection.getContentLength()); final String essentialVersion = getEssentialVersionMeta(gameVersion).get("version").getAsString(); - final Path target = modsDir.resolve(String.format("Essential %s (%s).jar", gameVersion, essentialVersion)); + final Path target = modsDir.resolve(String.format("Essential %s (%s).jar", essentialVersion, gameVersion)); final Path tempFile = Files.createTempFile("Dedicated Essential jar", ""); try ( From a1a5624abc0dc147d9d1acb86d928295ca2f8073 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:11:06 -0700 Subject: [PATCH 16/30] stage2/ml9: acquire version first and use it for download meta --- .../essential/loader/stage2/DedicatedJarLoader.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java index 65b728e..a180788 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java @@ -22,17 +22,18 @@ public class DedicatedJarLoader { "essential.download.url", System.getenv().getOrDefault("ESSENTIAL_DOWNLOAD_URL", "https://api.essential.gg/mods") ); - private static final String VERSION_URL = BASE_URL + "/v1/essential:essential-pinned/versions/stable/platforms/%s"; + private static final String VERSION_URL = BASE_URL + "/v1/essential:essential-pinned/versions/%s/platforms/%s"; private static final String DOWNLOAD_URL = VERSION_URL + "/download"; protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gameVersion) throws IOException { - final JsonObject meta = getEssentialDownloadMeta(gameVersion); + final String essentialVersion = getEssentialVersionMeta(gameVersion).get("version").getAsString(); + + final JsonObject meta = getEssentialDownloadMeta(essentialVersion, gameVersion); final URL url = new URL(meta.get("url").getAsString()); final URLConnection connection = url.openConnection(); ui.setDownloadSize(connection.getContentLength()); - final String essentialVersion = getEssentialVersionMeta(gameVersion).get("version").getAsString(); final Path target = modsDir.resolve(String.format("Essential %s (%s).jar", essentialVersion, gameVersion)); final Path tempFile = Files.createTempFile("Dedicated Essential jar", ""); @@ -63,10 +64,10 @@ private static JsonObject getEssentialMeta(URL url) throws IOException { } private static JsonObject getEssentialVersionMeta(String gameVersion) throws IOException { - return getEssentialMeta(new URL(String.format(VERSION_URL, gameVersion))); + return getEssentialMeta(new URL(String.format(VERSION_URL, "stable", gameVersion))); } - private static JsonObject getEssentialDownloadMeta(String gameVersion) throws IOException { - return getEssentialMeta(new URL(String.format(DOWNLOAD_URL, gameVersion))); + private static JsonObject getEssentialDownloadMeta(String essentialVersion, String gameVersion) throws IOException { + return getEssentialMeta(new URL(String.format(DOWNLOAD_URL, essentialVersion, gameVersion))); } } From 3df7c68e6833077f441ef6db40d88835a642feb3 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:12:42 -0700 Subject: [PATCH 17/30] stage2/ml9: use dashed mc version for api --- .../java/gg/essential/loader/stage2/DedicatedJarLoader.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java index a180788..c4acdfc 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java @@ -26,9 +26,10 @@ public class DedicatedJarLoader { private static final String DOWNLOAD_URL = VERSION_URL + "/download"; protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gameVersion) throws IOException { - final String essentialVersion = getEssentialVersionMeta(gameVersion).get("version").getAsString(); + final String apiVersion = gameVersion.replace('.', '-'); + final String essentialVersion = getEssentialVersionMeta(apiVersion).get("version").getAsString(); - final JsonObject meta = getEssentialDownloadMeta(essentialVersion, gameVersion); + final JsonObject meta = getEssentialDownloadMeta(essentialVersion, apiVersion); final URL url = new URL(meta.get("url").getAsString()); final URLConnection connection = url.openConnection(); From 552c6cb712c4636191bfc30fa18180a0a9ac2a5c Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:19:10 -0700 Subject: [PATCH 18/30] stage2/ml9: adjust restart ui wording --- .../main/java/gg/essential/loader/stage2/EssentialLoader.java | 2 +- .../java/gg/essential/loader/stage2/components/RestartUI.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java index 6e09732..acb370d 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java @@ -47,7 +47,7 @@ public void loadFromMixin(Path gameDir) { LogManager.getLogger().warn("Failed to download dedicated jar:", e); } finally { ui.complete(); - ForkedRestartUI restartUI = new ForkedRestartUI("Restart Required!", "One of the mods you have installed requires Essential. To complete the installation process, please restart minecraft."); + ForkedRestartUI restartUI = new ForkedRestartUI("Restart Required", "One of the mods you have installed requires Essential. To complete the installation process, please restart Minecraft."); restartUI.show(); restartUI.waitForClose(); } diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java index c6bff2b..1605301 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java @@ -47,7 +47,7 @@ public void show() { final JPanel buttons = new JPanel(); buttons.setOpaque(false); buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS)); - buttons.add(makeButton("Restart", COLOR_PRIMARY_BUTTON, COLOR_BUTTON_HOVER, () -> closedFuture.complete(true))); + buttons.add(makeButton("Quit Game", COLOR_PRIMARY_BUTTON, COLOR_BUTTON_HOVER, () -> closedFuture.complete(true))); content.add(buttons); content.add(Box.createVerticalStrut(32 - Y_SHADOW)); From 68b191801a0f277e2dc087ffd9ef7bc302fbded1 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Thu, 20 Jun 2024 02:02:23 -0700 Subject: [PATCH 19/30] stage2/ml9: change exception handling to stop showing restart ui when failed --- .../gg/essential/loader/stage2/EssentialLoader.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java index acb370d..9c99834 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java @@ -34,7 +34,7 @@ public void load() { } @SuppressWarnings("unused") // called via reflection from stage1 - public void loadFromMixin(Path gameDir) { + public void loadFromMixin(Path gameDir) throws IOException { final Path modsDir = gameDir.resolve("mods"); LoaderUI ui = LoaderUI.all( new LoaderLoggingUI().updatesEveryMillis(1000), @@ -43,14 +43,12 @@ public void loadFromMixin(Path gameDir) { ui.start(); try { DedicatedJarLoader.downloadDedicatedJar(ui, modsDir, "forge_" + FMLLoader.versionInfo().mcVersion()); - } catch (IOException e) { - LogManager.getLogger().warn("Failed to download dedicated jar:", e); } finally { ui.complete(); - ForkedRestartUI restartUI = new ForkedRestartUI("Restart Required", "One of the mods you have installed requires Essential. To complete the installation process, please restart Minecraft."); - restartUI.show(); - restartUI.waitForClose(); } + ForkedRestartUI restartUI = new ForkedRestartUI("Restart Required", "One of the mods you have installed requires Essential. To complete the installation process, please restart Minecraft."); + restartUI.show(); + restartUI.waitForClose(); System.exit(0); } } From f7e7347f696d14d36b6fddc3ca013e1ff132720b Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Thu, 27 Jun 2024 16:24:19 -0700 Subject: [PATCH 20/30] stage2/ml9: reword restart ui using mod name marker file --- .../loader/stage2/EssentialLoader.java | 16 +++++++-- .../stage2/components/ForkedRestartUI.java | 25 ++++++++------ .../loader/stage2/components/RestartUI.java | 33 ++++++++++++++----- 3 files changed, 54 insertions(+), 20 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java index 9c99834..f45cfa5 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java @@ -8,7 +8,13 @@ import org.apache.logging.log4j.LogManager; import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * The initial entrypoint for stage2. With ModLauncher, we cannot yet know the MC version at this point, so this is a @@ -34,7 +40,7 @@ public void load() { } @SuppressWarnings("unused") // called via reflection from stage1 - public void loadFromMixin(Path gameDir) throws IOException { + public void loadFromMixin(Path gameDir) throws Exception { final Path modsDir = gameDir.resolve("mods"); LoaderUI ui = LoaderUI.all( new LoaderLoggingUI().updatesEveryMillis(1000), @@ -46,7 +52,13 @@ public void loadFromMixin(Path gameDir) throws IOException { } finally { ui.complete(); } - ForkedRestartUI restartUI = new ForkedRestartUI("Restart Required", "One of the mods you have installed requires Essential. To complete the installation process, please restart Minecraft."); + List modNameMarkers = Collections.list(this.getClass().getClassLoader().getResources("META-INF/essential-loader-mod-name.txt")); + List modNames = new ArrayList<>(); + for (URL url : modNameMarkers) { + String modName = Files.readString(Paths.get(url.toURI())); + modNames.add(modName); + } + ForkedRestartUI restartUI = new ForkedRestartUI(modNames); restartUI.show(); restartUI.waitForClose(); System.exit(0); diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java index bea4ba9..830f3ff 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java @@ -7,16 +7,16 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; public class ForkedRestartUI { private final Logger LOGGER = LogManager.getLogger(); - private final String title; - private final String description; + private final List mods; private ForkedJvm jvm; - public ForkedRestartUI(String title, String description) { - this.title = title; - this.description = description; + public ForkedRestartUI(List mods) { + this.mods = mods; } public void show() { @@ -24,8 +24,11 @@ public void show() { this.jvm = new ForkedJvm(getClass()); DataOutputStream out = new DataOutputStream(this.jvm.process.getOutputStream()); - out.writeUTF(title); - out.writeUTF(description); + for (String name : this.mods) { + out.writeBoolean(true); // signal more entries + out.writeUTF(name); + } + out.writeBoolean(false); // signal end of list out.flush(); } catch (IOException e) { LOGGER.warn("Failed to fork JVM for RestartUI:", e); @@ -50,12 +53,14 @@ public Boolean waitForClose() { public static void main(String[] args) throws IOException { DataInputStream in = new DataInputStream(System.in); - String title = in.readUTF(); - String description = in.readUTF(); + List mods = new ArrayList<>(); + while(in.readBoolean()) { + mods.add(in.readUTF()); + } Boolean verdict = null; try { - RestartUI ui = new RestartUI(title, description); + RestartUI ui = new RestartUI(mods); ui.show(); verdict = ui.waitForClose(); diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java index 1605301..0e2b538 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java @@ -15,12 +15,10 @@ public class RestartUI implements EssentialStyle { private final JFrame frame = makeFrame(it -> closedFuture.complete(null)); - private final String title; - private final String description; + private final List mods; - public RestartUI(String title, String description) { - this.title = title; - this.description = description; + public RestartUI(List mods) { + this.mods = mods; } public void show() { @@ -30,9 +28,9 @@ public void show() { content.setBorder(new EmptyBorder(0, 60 - X_SHADOW, 0, 60 - X_SHADOW)); content.add(Box.createHorizontalStrut(CONTENT_WIDTH)); - htmlLabels.add(makeTitle(content, html(centered(title)))); + htmlLabels.add(makeTitle(content, html(centered("Please restart your game to automatically install Essential.")))); - final JLabel explanation = new JLabel(html(centered(description)), SwingConstants.CENTER); + final JLabel explanation = new JLabel(html(centered("The following mods require Essential Mod's API:")), SwingConstants.CENTER); explanation.setMaximumSize(new Dimension(CONTENT_WIDTH, Integer.MAX_VALUE)); explanation.setForeground(COLOR_FOREGROUND); explanation.setAlignmentX(Container.CENTER_ALIGNMENT); @@ -42,6 +40,25 @@ public void show() { content.add(explanation); htmlLabels.add(explanation); + content.add(Box.createVerticalStrut(19)); + + final JPanel modList = new JPanel(); + modList.setMaximumSize(new Dimension(CONTENT_WIDTH, Integer.MAX_VALUE)); + modList.setBackground(COLOR_BACKGROUND); + modList.setLayout(new BoxLayout(modList, BoxLayout.Y_AXIS)); + content.add(modList); + + for (String modName : mods) { + final JLabel text = new JLabel(html(centered(modName)), SwingConstants.CENTER); + text.setForeground(COLOR_HIGHLIGHT); + text.setAlignmentX(Container.CENTER_ALIGNMENT); + if (Fonts.mediumItalic != null) { + text.setFont(Fonts.mediumItalic.deriveFont(16F)); + } + modList.add(text); + htmlLabels.add(text); + } + content.add(Box.createVerticalStrut(32 - Y_SHADOW)); final JPanel buttons = new JPanel(); @@ -72,7 +89,7 @@ public void close() { } public static void main(String[] args) { - RestartUI ui = new RestartUI("Restart required!", "A restart is required for something."); + RestartUI ui = new RestartUI(List.of("Skytils")); ui.show(); System.out.println(ui.waitForClose()); } From 127a548d5fe6b7062485a36c24b7a80fff85d1b1 Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Fri, 28 Jun 2024 12:39:37 -0700 Subject: [PATCH 21/30] stage2/ml9: default empty mod names list to "Unknown" --- .../main/java/gg/essential/loader/stage2/EssentialLoader.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java index f45cfa5..f600126 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java @@ -58,6 +58,9 @@ public void loadFromMixin(Path gameDir) throws Exception { String modName = Files.readString(Paths.get(url.toURI())); modNames.add(modName); } + if (modNames.isEmpty()) { + modNames = List.of("Unknown"); + } ForkedRestartUI restartUI = new ForkedRestartUI(modNames); restartUI.show(); restartUI.waitForClose(); From 0995ac5ebe59d606d76482bbd98e2d19c5967127 Mon Sep 17 00:00:00 2001 From: Sychic <47618543+Sychic@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:06:39 -0400 Subject: [PATCH 22/30] stage0/ml9: remove unnecessary mixin config --- stage0/modlauncher9/build.gradle | 7 ------- 1 file changed, 7 deletions(-) diff --git a/stage0/modlauncher9/build.gradle b/stage0/modlauncher9/build.gradle index 6f3a469..11b2cbd 100644 --- a/stage0/modlauncher9/build.gradle +++ b/stage0/modlauncher9/build.gradle @@ -11,11 +11,4 @@ dependencies { // as of forge 37.1 for MC 1.17.1, mixin is shipped with forge // https://github.com/MinecraftForge/MinecraftForge/commit/c8d3ad1d1c977513b75e6aa3dd81c6ed9463bcae compileOnly("org.spongepowered:mixin:0.8.5") -} - -jar { - manifest { - // this is removed when people include the loader however better to have it than not - attributes("MixinConfigs": "gg.essential.loader.stage0.EssentialStage0MixinPlugin") - } } \ No newline at end of file From 28a3967761dcdba48d6b2ff8e5ca1aa9d95f0099 Mon Sep 17 00:00:00 2001 From: Sychic <47618543+Sychic@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:12:41 -0400 Subject: [PATCH 23/30] stage1/ml9: use same variable for mixin path mc version --- .../essential/loader/stage1/EssentialMixinPluginLoader.java | 4 ++-- .../loader/stage1/EssentialTransformationService.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java index 68c5f54..f3a8523 100644 --- a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java +++ b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java @@ -4,11 +4,11 @@ import cpw.mods.modlauncher.api.IEnvironment; import cpw.mods.modlauncher.api.ITransformationService; import cpw.mods.modlauncher.api.TypesafeMap; -import net.minecraftforge.fml.loading.FMLLoader; import java.nio.file.Path; import java.nio.file.Paths; +import static gg.essential.loader.stage1.EssentialTransformationService.MC_VERSION; import static gg.essential.loader.stage1.EssentialTransformationServiceBase.KEY_LOADED; @SuppressWarnings("unused") @@ -28,7 +28,7 @@ public EssentialMixinPluginLoader() throws Exception { .orElse(Paths.get(".")); // variant and game version to match transformation service path - EssentialLoader loader = EssentialLoader.getInstance("modlauncher9", "forge_1.17.1"); + EssentialLoader loader = EssentialLoader.getInstance("modlauncher9", "forge_" + MC_VERSION); loader.load(gameDir); loader.getStage2().getClass() diff --git a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialTransformationService.java b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialTransformationService.java index 9fa54d5..19e6544 100644 --- a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialTransformationService.java +++ b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialTransformationService.java @@ -23,7 +23,7 @@ public class EssentialTransformationService extends EssentialTransformationServi // the first one we support (stage2 will be the same for all MC versions on the same stage1 anyway) and once we are // in stage2, we can re-query at a later point as needed (but we always retain the ability to run an up-to-date // stage2 as early as possible). - private static final String MC_VERSION = "1.17.1"; + protected static final String MC_VERSION = "1.17.1"; public EssentialTransformationService(final ITransformationService stage0) throws Exception { super(stage0, FallbackTransformationService::new, "modlauncher9", MC_VERSION); From 61f3611bdee34d793de87442a70e88f1cd0e3a3f Mon Sep 17 00:00:00 2001 From: Sychic <47618543+Sychic@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:31:40 -0400 Subject: [PATCH 24/30] stage2/ml9: add explicit line break to `RestartUI` --- .../java/gg/essential/loader/stage2/components/RestartUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java index 0e2b538..02bd234 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java @@ -30,7 +30,7 @@ public void show() { htmlLabels.add(makeTitle(content, html(centered("Please restart your game to automatically install Essential.")))); - final JLabel explanation = new JLabel(html(centered("The following mods require Essential Mod's API:")), SwingConstants.CENTER); + final JLabel explanation = new JLabel(html(centered("The following mods require
Essential Mod's API:")), SwingConstants.CENTER); explanation.setMaximumSize(new Dimension(CONTENT_WIDTH, Integer.MAX_VALUE)); explanation.setForeground(COLOR_FOREGROUND); explanation.setAlignmentX(Container.CENTER_ALIGNMENT); From 35136cbdd6e5b9fef53011ab2bb2cf47fbad7f41 Mon Sep 17 00:00:00 2001 From: Sychic <47618543+Sychic@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:34:47 -0400 Subject: [PATCH 25/30] stage2/ml9: fix logic error in `ForkedRestartUI` --- .../gg/essential/loader/stage2/components/ForkedRestartUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java index 830f3ff..8582b44 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java @@ -36,7 +36,7 @@ public void show() { } public Boolean waitForClose() { - if (this.jvm != null) return null; + if (this.jvm == null) return null; try { int verdict = this.jvm.process.getInputStream().read(); From a285f5f19509b15c80cc17dad80e8932c791c5a1 Mon Sep 17 00:00:00 2001 From: Sychic <47618543+Sychic@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:56:40 -0400 Subject: [PATCH 26/30] stage2/ml9: remove boolean return type from `RestartUI#waitForClose` --- .../stage2/components/ForkedRestartUI.java | 21 ++++++------------- .../loader/stage2/components/RestartUI.java | 11 +++++----- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java index 8582b44..d71f8aa 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java @@ -35,15 +35,13 @@ public void show() { } } - public Boolean waitForClose() { - if (this.jvm == null) return null; + public void waitForClose() { + if (this.jvm == null) return; try { - int verdict = this.jvm.process.getInputStream().read(); - return verdict == 1 ? Boolean.TRUE : verdict == 2 ? Boolean.FALSE : null; - } catch (IOException e) { + this.jvm.process.getInputStream().wait(); + } catch (InterruptedException e) { LOGGER.warn("Failed to wait for RestartUI to close:", e); - return null; } finally { this.jvm.close(); this.jvm = null; @@ -58,23 +56,16 @@ public static void main(String[] args) throws IOException { mods.add(in.readUTF()); } - Boolean verdict = null; try { RestartUI ui = new RestartUI(mods); ui.show(); - verdict = ui.waitForClose(); + ui.waitForClose(); } catch (Throwable t) { t.printStackTrace(); } - if (verdict == Boolean.TRUE) { - System.out.write(1); - } else if (verdict == Boolean.FALSE) { - System.out.write(2); - } else { - System.out.write(0); - } System.out.flush(); + System.out.close(); } } diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java index 02bd234..85b8771 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/RestartUI.java @@ -11,7 +11,7 @@ import static gg.essential.loader.stage2.components.ButtonShadowBorder.Y_SHADOW; public class RestartUI implements EssentialStyle { - private final CompletableFuture closedFuture = new CompletableFuture<>(); + private final CompletableFuture closedFuture = new CompletableFuture<>(); private final JFrame frame = makeFrame(it -> closedFuture.complete(null)); @@ -64,7 +64,7 @@ public void show() { final JPanel buttons = new JPanel(); buttons.setOpaque(false); buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS)); - buttons.add(makeButton("Quit Game", COLOR_PRIMARY_BUTTON, COLOR_BUTTON_HOVER, () -> closedFuture.complete(true))); + buttons.add(makeButton("Quit Game", COLOR_PRIMARY_BUTTON, COLOR_BUTTON_HOVER, () -> closedFuture.complete(null))); content.add(buttons); content.add(Box.createVerticalStrut(32 - Y_SHADOW)); @@ -78,10 +78,9 @@ public void show() { frame.setVisible(true); } - public Boolean waitForClose() { - Boolean verdict = closedFuture.join(); + public void waitForClose() { + closedFuture.join(); close(); - return verdict; } public void close() { @@ -91,6 +90,6 @@ public void close() { public static void main(String[] args) { RestartUI ui = new RestartUI(List.of("Skytils")); ui.show(); - System.out.println(ui.waitForClose()); + ui.waitForClose(); } } From 66e4e4059ca3aed3e90a1181cb9ef83d674d84e0 Mon Sep 17 00:00:00 2001 From: Sychic <47618543+Sychic@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:59:22 -0400 Subject: [PATCH 27/30] stage2/ml9: make sure temp file is deleted --- .../java/gg/essential/loader/stage2/DedicatedJarLoader.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java index c4acdfc..8ceae71 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java @@ -52,6 +52,8 @@ protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gam } Files.move(tempFile, target, ATOMIC_MOVE); + } finally { + Files.deleteIfExists(tempFile); } } From ed7842987ef4be6bc2f8c9f3eab6d7c12a94ed20 Mon Sep 17 00:00:00 2001 From: Sychic <47618543+Sychic@users.noreply.github.com> Date: Sat, 24 Aug 2024 15:08:12 -0400 Subject: [PATCH 28/30] stage2/ml9: move where file is moved and change temp file name this should reduce issues where the file system may prevent the file move from happening. F.ex. cross file systems, or file being open due to the stream. --- .../gg/essential/loader/stage2/DedicatedJarLoader.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java index 8ceae71..26eb113 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/DedicatedJarLoader.java @@ -36,7 +36,7 @@ protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gam ui.setDownloadSize(connection.getContentLength()); final Path target = modsDir.resolve(String.format("Essential %s (%s).jar", essentialVersion, gameVersion)); - final Path tempFile = Files.createTempFile("Dedicated Essential jar", ""); + final Path tempFile = Files.createFile(modsDir.resolve("Essential Jar Download.jar.tmp")); try ( final InputStream in = connection.getInputStream(); @@ -50,10 +50,12 @@ protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gam totalRead += read; ui.setDownloaded(totalRead); } - - Files.move(tempFile, target, ATOMIC_MOVE); } finally { - Files.deleteIfExists(tempFile); + try { + Files.move(tempFile, target, ATOMIC_MOVE); + } finally { + Files.deleteIfExists(tempFile); + } } } From 2955dfdd30230551239d95cfa5206b121a92b4f8 Mon Sep 17 00:00:00 2001 From: Sychic <47618543+Sychic@users.noreply.github.com> Date: Sat, 24 Aug 2024 15:10:43 -0400 Subject: [PATCH 29/30] stage1/ml9: improve comment in `EssentialMixinPluginLoader` --- .../gg/essential/loader/stage1/EssentialMixinPluginLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java index f3a8523..5d46141 100644 --- a/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java +++ b/stage1/modlauncher9/src/main/java/gg/essential/loader/stage1/EssentialMixinPluginLoader.java @@ -15,7 +15,7 @@ public class EssentialMixinPluginLoader { public EssentialMixinPluginLoader() throws Exception { - // Check if another transformation service has already loaded stage2 (we do not want to load it twice) + // Check if stage 2 has already been loaded by a transformation service final TypesafeMap blackboard = Launcher.INSTANCE.blackboard(); final TypesafeMap.Key LOADED = TypesafeMap.Key.getOrCreate(blackboard, KEY_LOADED, ITransformationService.class); From 80bbf2648b487a2dd3c59513716a385780eaf50a Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Sun, 25 Aug 2024 11:45:30 -0400 Subject: [PATCH 30/30] stage2/ml9: fix using wrong method to wait for forked process to terminate --- .../essential/loader/stage2/components/ForkedRestartUI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java index d71f8aa..13bf3d6 100644 --- a/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java +++ b/stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/components/ForkedRestartUI.java @@ -39,8 +39,8 @@ public void waitForClose() { if (this.jvm == null) return; try { - this.jvm.process.getInputStream().wait(); - } catch (InterruptedException e) { + this.jvm.process.getInputStream().read(); + } catch (IOException e) { LOGGER.warn("Failed to wait for RestartUI to close:", e); } finally { this.jvm.close();