From a3634e4fe60a3fd9757480c507e27b257d42b3bf Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 5 Jan 2026 16:32:27 +0000 Subject: [PATCH 1/5] Fix lwjgl3ify 3.0 compatibility in the exit confirmation code --- addon.gradle | 9 --- build.gradle | 5 -- build.gradle.kts | 23 +++++++ settings.gradle | 2 +- .../dreammaster/lwjgl3ify/ConfirmExitSdl.java | 67 +++++++++++++++++++ .../early/MixinMinecraft_ConfirmExit.java | 18 +++++ 6 files changed, 109 insertions(+), 15 deletions(-) delete mode 100644 addon.gradle delete mode 100644 build.gradle create mode 100644 build.gradle.kts create mode 100644 src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java diff --git a/addon.gradle b/addon.gradle deleted file mode 100644 index 70474015e5..0000000000 --- a/addon.gradle +++ /dev/null @@ -1,9 +0,0 @@ -test { - useJUnitPlatform() - testLogging { - events "passed", "skipped", "failed" - } -} -configurations { - testImplementation.extendsFrom compileOnly -} diff --git a/build.gradle b/build.gradle deleted file mode 100644 index e57a16f9f1..0000000000 --- a/build.gradle +++ /dev/null @@ -1,5 +0,0 @@ -//version: 1707058017 - -plugins { - id 'com.gtnewhorizons.gtnhconvention' -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000000..26d40e8ecb --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + id("com.gtnewhorizons.gtnhconvention") +} + +tasks.test.configure { + useJUnitPlatform() + testLogging { + events ("passed", "skipped", "failed") + } +} + +configurations { + testImplementation.get().extendsFrom(compileOnly.get()) +} + +// Allow optional lwjgl3 usage, make sure to hide it behind the appropriate conditionals +// This can't be in dependencies.gradle due to need to freeze the lwjgl3 version property +val lwjgl3Version = project.minecraft.lwjgl3Version.get()!! +dependencies { + compileOnly("org.lwjgl:lwjgl-sdl:${lwjgl3Version}") { isTransitive = false } + compileOnly("org.lwjgl:lwjgl:${lwjgl3Version}") { isTransitive = false } + compileOnly("com.github.GTNewHorizons:lwjgl3ify:3.0.3:dev") { isTransitive = false } +} diff --git a/settings.gradle b/settings.gradle index 9ce4966b4d..647b0d4a64 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.7' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.10' } diff --git a/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java new file mode 100644 index 0000000000..453b265d0c --- /dev/null +++ b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java @@ -0,0 +1,67 @@ +package com.dreammaster.lwjgl3ify; + +import static org.lwjgl.sdl.SDLMessageBox.*; + +import java.nio.IntBuffer; + +import me.eigenraven.lwjgl3ify.api.Lwjgl3Aware; +import net.minecraft.util.StatCollector; + +import org.lwjgl.sdl.SDLError; +import org.lwjgl.sdl.SDL_MessageBoxButtonData; +import org.lwjgl.sdl.SDL_MessageBoxData; +import org.lwjgl.system.MemoryStack; +import org.lwjglx.opengl.Display; + +import com.dreammaster.coremod.DreamCoreMod; +import com.dreammaster.lib.Refstrings; + +@Lwjgl3Aware +public class ConfirmExitSdl { + + // Keep as static final ints to avoid adding a classloading dependency when used + public static final int BUTTON_YES = 0; + public static final int BUTTON_NO = 1; + public static final int BUTTON_NEVER = 2; + + private static String translateOrDefault(String key, String defaultValue) { + return StatCollector.canTranslate(key) ? StatCollector.translateToLocal(key) : defaultValue; + } + + /** + * @return 0 for Yes, 1 for No, + */ + @SuppressWarnings("resource") + public static int showExitDialog() { + try (MemoryStack stack = MemoryStack.stackPush()) { + final IntBuffer selectedOption = stack.ints(1); + final SDL_MessageBoxData box = SDL_MessageBoxData.calloc(stack); + + final String yesText = translateOrDefault("dreamcraft.gui.quitmessage.yes", "Yes"); + final String noText = translateOrDefault("dreamcraft.gui.quitmessage.no", "No"); + final String neverText = translateOrDefault("dreamcraft.gui.quitmessage.never", "Don't Show Again!"); + final String messageText = translateOrDefault( + "dreamcraft.gui.quitmessage", + "Are you sure you want to exit the game?"); + + box.flags(SDL_MESSAGEBOX_WARNING); + box.window(Display.getWindow()); + box.title(stack.ASCII(Refstrings.NAME)); + box.message(stack.ASCII(messageText)); + + final SDL_MessageBoxButtonData.Buffer buttons = SDL_MessageBoxButtonData.calloc(3, stack); + buttons.get(BUTTON_YES).set(SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, BUTTON_YES, stack.ASCII(yesText)); + buttons.get(BUTTON_NO).set(SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, BUTTON_NO, stack.ASCII(noText)); + buttons.get(BUTTON_NEVER).set(0, BUTTON_NEVER, stack.ASCII(neverText)); + box.buttons(buttons); + + if (!SDL_ShowMessageBox(box, selectedOption)) { + DreamCoreMod.logger + .error("Could not create exit confirmation message box: {}", SDLError.SDL_GetError()); + // Assume it's ok to quit in case the message box cannot be spawned + return BUTTON_YES; + } + return selectedOption.get(0); + } + } +} diff --git a/src/main/java/com/dreammaster/mixin/mixins/early/MixinMinecraft_ConfirmExit.java b/src/main/java/com/dreammaster/mixin/mixins/early/MixinMinecraft_ConfirmExit.java index fcf6f2bf09..8a18df2e42 100644 --- a/src/main/java/com/dreammaster/mixin/mixins/early/MixinMinecraft_ConfirmExit.java +++ b/src/main/java/com/dreammaster/mixin/mixins/early/MixinMinecraft_ConfirmExit.java @@ -7,6 +7,7 @@ import javax.swing.JOptionPane; import net.minecraft.client.Minecraft; +import net.minecraft.launchwrapper.Launch; import net.minecraft.util.StatCollector; import org.spongepowered.asm.mixin.Mixin; @@ -19,6 +20,7 @@ import com.dreammaster.client.util.IconLoader; import com.dreammaster.coremod.DreamCoreMod; import com.dreammaster.lib.Refstrings; +import com.dreammaster.lwjgl3ify.ConfirmExitSdl; @Mixin(Minecraft.class) public abstract class MixinMinecraft_ConfirmExit { @@ -40,6 +42,22 @@ public abstract class MixinMinecraft_ConfirmExit { if (!this.dreamcraft$waitingDialogQuit) { this.dreamcraft$waitingDialogQuit = true; new Thread(() -> { + // Do not use Swing when lwjgl3ify 3.x is active + if ((Integer) Launch.blackboard.getOrDefault("lwjgl3ify:major-version", Integer.MIN_VALUE) >= 3) { + final int choice = ConfirmExitSdl.showExitDialog(); + if (choice == ConfirmExitSdl.BUTTON_YES) { + this.dreamcraft$isCloseRequested = true; + this.shutdown(); + } else if (choice == ConfirmExitSdl.BUTTON_NEVER) { + this.dreamcraft$isCloseRequested = true; + DreamCoreMod.disableShowConfirmExitWindow(); + this.shutdown(); + } + this.dreamcraft$waitingDialogQuit = false; + + return; + } + final JFrame frame = new JFrame(); frame.setAlwaysOnTop(true); final URL resource = IconLoader.class.getClassLoader() From 2159f219375e5f7aad68c2c769d5023780904728 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:39:00 +0000 Subject: [PATCH 2/5] Spotless apply for branch fix-headless-exit for #1545 (#1546) Co-authored-by: GitHub GTNH Actions <> --- src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java index 453b265d0c..0c3202e7db 100644 --- a/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java +++ b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java @@ -4,7 +4,6 @@ import java.nio.IntBuffer; -import me.eigenraven.lwjgl3ify.api.Lwjgl3Aware; import net.minecraft.util.StatCollector; import org.lwjgl.sdl.SDLError; @@ -16,6 +15,8 @@ import com.dreammaster.coremod.DreamCoreMod; import com.dreammaster.lib.Refstrings; +import me.eigenraven.lwjgl3ify.api.Lwjgl3Aware; + @Lwjgl3Aware public class ConfirmExitSdl { From 6da399e4d448c0bd1440d2cb163f252063ff318a Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Sun, 11 Jan 2026 08:58:45 +0000 Subject: [PATCH 3/5] Use UTF8 C string conversion routines --- .../java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java index 0c3202e7db..88e7f553d6 100644 --- a/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java +++ b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java @@ -47,13 +47,13 @@ public static int showExitDialog() { box.flags(SDL_MESSAGEBOX_WARNING); box.window(Display.getWindow()); - box.title(stack.ASCII(Refstrings.NAME)); - box.message(stack.ASCII(messageText)); + box.title(stack.UTF8(Refstrings.NAME)); + box.message(stack.UTF8(messageText)); final SDL_MessageBoxButtonData.Buffer buttons = SDL_MessageBoxButtonData.calloc(3, stack); - buttons.get(BUTTON_YES).set(SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, BUTTON_YES, stack.ASCII(yesText)); - buttons.get(BUTTON_NO).set(SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, BUTTON_NO, stack.ASCII(noText)); - buttons.get(BUTTON_NEVER).set(0, BUTTON_NEVER, stack.ASCII(neverText)); + buttons.get(BUTTON_YES).set(SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, BUTTON_YES, stack.UTF8(yesText)); + buttons.get(BUTTON_NO).set(SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, BUTTON_NO, stack.UTF8(noText)); + buttons.get(BUTTON_NEVER).set(0, BUTTON_NEVER, stack.UTF8(neverText)); box.buttons(buttons); if (!SDL_ShowMessageBox(box, selectedOption)) { From a720ef4f18c0723f02fb5abd48235c0c15aa3d98 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 12 Jan 2026 21:28:48 +0000 Subject: [PATCH 4/5] Update src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java Co-authored-by: Wilhelm Schuster --- src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java index 88e7f553d6..ab867ca845 100644 --- a/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java +++ b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java @@ -38,6 +38,9 @@ public static int showExitDialog() { final IntBuffer selectedOption = stack.ints(1); final SDL_MessageBoxData box = SDL_MessageBoxData.calloc(stack); +// This dialog might get shown in a situation where localization isn't loaded, so this allows us to set a hardcoded +// default. +// See the corresponding mixin for the Minecraft class for more details. final String yesText = translateOrDefault("dreamcraft.gui.quitmessage.yes", "Yes"); final String noText = translateOrDefault("dreamcraft.gui.quitmessage.no", "No"); final String neverText = translateOrDefault("dreamcraft.gui.quitmessage.never", "Don't Show Again!"); From f09a337ce79050a96f222b47e3535c292d24b8a1 Mon Sep 17 00:00:00 2001 From: Wilhelm Schuster Date: Mon, 12 Jan 2026 22:37:47 +0100 Subject: [PATCH 5/5] spotless fix --- src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java index ab867ca845..13edfbf18e 100644 --- a/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java +++ b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java @@ -38,9 +38,9 @@ public static int showExitDialog() { final IntBuffer selectedOption = stack.ints(1); final SDL_MessageBoxData box = SDL_MessageBoxData.calloc(stack); -// This dialog might get shown in a situation where localization isn't loaded, so this allows us to set a hardcoded -// default. -// See the corresponding mixin for the Minecraft class for more details. + // This dialog might get shown in a situation where localization isn't loaded, so this allows us to set a + // hardcoded default. + // See the corresponding mixin for the Minecraft class for more details. final String yesText = translateOrDefault("dreamcraft.gui.quitmessage.yes", "Yes"); final String noText = translateOrDefault("dreamcraft.gui.quitmessage.no", "No"); final String neverText = translateOrDefault("dreamcraft.gui.quitmessage.never", "Don't Show Again!");