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/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java new file mode 100644 index 0000000000..13edfbf18e --- /dev/null +++ b/src/main/java/com/dreammaster/lwjgl3ify/ConfirmExitSdl.java @@ -0,0 +1,71 @@ +package com.dreammaster.lwjgl3ify; + +import static org.lwjgl.sdl.SDLMessageBox.*; + +import java.nio.IntBuffer; + +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; + +import me.eigenraven.lwjgl3ify.api.Lwjgl3Aware; + +@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); + + // 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!"); + 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.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.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)) { + 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()