diff --git a/common/src/main/java/com/vaporvee/loadsupport/Allocated.java b/common/src/main/java/com/vaporvee/loadsupport/Allocated.java index ef95e10..cc8b200 100644 --- a/common/src/main/java/com/vaporvee/loadsupport/Allocated.java +++ b/common/src/main/java/com/vaporvee/loadsupport/Allocated.java @@ -4,6 +4,7 @@ import com.vaporvee.loadsupport.platform.Services; import javax.swing.*; import java.awt.*; +import java.net.URI; public class Allocated { public static float memoryInGB; @@ -15,37 +16,75 @@ public class Allocated { Constants.LOG.info(String.format("Allocated Memory: %.1f GB", memoryInGB)); } - public static String[] getWarningMessage(){ + public static String[] getWarningMessage() { Config config = Services.CONFIG.getConfig(); - return new String[]{config.errorTitle, config.errorDescription - .replace("{minMemory}", String.valueOf(config.minMemory)) - .replace("{currentMemory}", String.valueOf(memoryInGB))}; - }; - static boolean errorWindowOpen = false; + String title = stripHtml(config.errorTitle); + String minMemoryText = stripHtml(config.errorMinMemory); + String currentMemoryText = stripHtml(config.errorCurrentMemory); + + String minMemoryFormatted = String.format("%.1f", config.minMemory); + String currentMemoryFormatted = String.format("%.1f", memoryInGB); + + String heading = Constants.MOD_NAME + " - " + title; + String body = minMemoryText.replace("{minMemory}", minMemoryFormatted) + + "

" + + currentMemoryText.replace("{currentMemory}", currentMemoryFormatted); + return new String[] { heading, body, config.memoryInfoLink }; + } + + private static String stripHtml(String input) { + return input == null ? "" : input.replaceAll("<[^>]*>", ""); + } + + public static boolean enoughMemory = true; private static JFrame errorWindow; - public static void createErrorWindow() { + public static boolean isWindowOpen(){ + return errorWindow.isDisplayable(); + } + + public static void createMemoryError() { try { - if (!errorWindowOpen) { - errorWindowOpen = true; + if (enoughMemory) { + enoughMemory = false; SwingUtilities.invokeLater(() -> { - errorWindow = new JFrame(getWarningMessage()[0]); + String[] warning = getWarningMessage(); + errorWindow = new JFrame(warning[0]); errorWindow.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - errorWindow.setSize(400, 200); + errorWindow.setSize(500, 350); errorWindow.setLocationRelativeTo(null); - JLabel message = new JLabel("

"+ getWarningMessage()[1]+"

", JLabel.CENTER); - JButton exitButton = new JButton("OK"); + JLabel message = new JLabel( + "

" + warning[1] + "

", + JLabel.CENTER + ); - exitButton.addActionListener(e -> { - errorWindow.dispose(); - //minecraftClient.stop(); // how to get client crossplatform? - }); + JButton okButton = new JButton("OK"); + okButton.addActionListener(e -> errorWindow.dispose()); + + int buttonCount = 1 + (!warning[2].isBlank() ? 1 : 0); + + JPanel buttonPanel = new JPanel(new GridLayout(1, buttonCount, 10, 0)); + buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + buttonPanel.add(okButton); + + if (!warning[2].isBlank()) { + JButton moreInfoButton = new JButton("More info"); + moreInfoButton.addActionListener(e -> { + try { + Desktop.getDesktop().browse(new URI(warning[2])); + } catch (Exception ex) { + Constants.LOG.error(String.valueOf(ex)); + } + }); + buttonPanel.add(moreInfoButton); + } errorWindow.setLayout(new BorderLayout()); errorWindow.add(message, BorderLayout.CENTER); - errorWindow.add(exitButton, BorderLayout.SOUTH); + errorWindow.add(buttonPanel, BorderLayout.SOUTH); errorWindow.setVisible(true); }); } diff --git a/common/src/main/java/com/vaporvee/loadsupport/CommonClass.java b/common/src/main/java/com/vaporvee/loadsupport/CommonClass.java index 2ad56a2..ecc04e4 100644 --- a/common/src/main/java/com/vaporvee/loadsupport/CommonClass.java +++ b/common/src/main/java/com/vaporvee/loadsupport/CommonClass.java @@ -20,7 +20,7 @@ public class CommonClass { System.setProperty("java.awt.headless", "false"); Constants.LOG.error("Not enough memory! Allocated memory in GB is {} but set in config is {}", Allocated.memoryInGB, config.minMemory); - Allocated.createErrorWindow(); + Allocated.createMemoryError(); } } else { Constants.LOG.warn("Load config is null!"); diff --git a/common/src/main/java/com/vaporvee/loadsupport/Config.java b/common/src/main/java/com/vaporvee/loadsupport/Config.java index 0c671a2..0571e8c 100644 --- a/common/src/main/java/com/vaporvee/loadsupport/Config.java +++ b/common/src/main/java/com/vaporvee/loadsupport/Config.java @@ -7,5 +7,7 @@ public class Config implements ConfigData { boolean startSound = true; float minMemory = 4.0f; String errorTitle = "Error: Not enough Java memory!"; - String errorDescription = "Please allocate at least {minMemory} GB of Java memory to your Minecraft Instance! You have currently {currentMemory} GB allocated."; + String errorMinMemory = "Please allocate at least {minMemory} GB of Java memory to your Minecraft instance!"; + String errorCurrentMemory = "You have currently {currentMemory} GB allocated."; + String memoryInfoLink = "https://github.com/vaporvee/LoadSupport/wiki/How-to-allocate-more-memory-to-your-Minecraft-instance"; } diff --git a/common/src/main/java/com/vaporvee/loadsupport/Constants.java b/common/src/main/java/com/vaporvee/loadsupport/Constants.java index 5d87f42..2d27d0a 100644 --- a/common/src/main/java/com/vaporvee/loadsupport/Constants.java +++ b/common/src/main/java/com/vaporvee/loadsupport/Constants.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; public class Constants { public static final String MOD_ID = "loadsupport"; - public static final String MOD_NAME = "LoadSupport"; + public static final String MOD_NAME = "Load Support"; public static final Logger LOG = LoggerFactory.getLogger(MOD_NAME); public static final float GIGABYTE = 1073741824f; } \ No newline at end of file diff --git a/neoforge/src/main/java/com/vaporvee/loadsupport/LoadSupport.java b/neoforge/src/main/java/com/vaporvee/loadsupport/LoadSupport.java index 98b1e1b..ba4dec0 100644 --- a/neoforge/src/main/java/com/vaporvee/loadsupport/LoadSupport.java +++ b/neoforge/src/main/java/com/vaporvee/loadsupport/LoadSupport.java @@ -2,6 +2,7 @@ package com.vaporvee.loadsupport; import com.vaporvee.loadsupport.platform.Services; +import net.neoforged.bus.api.Event; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.common.Mod; diff --git a/neoforge/src/main/java/com/vaporvee/loadsupport/mixin/MinecraftPauseMixin.java b/neoforge/src/main/java/com/vaporvee/loadsupport/mixin/MinecraftPauseMixin.java new file mode 100644 index 0000000..34f4cdb --- /dev/null +++ b/neoforge/src/main/java/com/vaporvee/loadsupport/mixin/MinecraftPauseMixin.java @@ -0,0 +1,21 @@ +package com.vaporvee.loadsupport.mixin; + +import com.vaporvee.loadsupport.Allocated; +import net.minecraft.client.Minecraft; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Minecraft.class) +public class MinecraftPauseMixin { + @Inject(method = "run", at = @At("HEAD"), cancellable = true) + private void onRunHead(CallbackInfo ci) { + if (!Allocated.enoughMemory) { + while (Allocated.isWindowOpen()) { + try { Thread.sleep(100); } catch (InterruptedException ignored) {} + } + ci.cancel(); + } + } +} diff --git a/neoforge/src/main/java/com/vaporvee/loadsupport/mixin/MixinTitleScreen.java b/neoforge/src/main/java/com/vaporvee/loadsupport/mixin/MixinTitleScreen.java deleted file mode 100644 index 83654d6..0000000 --- a/neoforge/src/main/java/com/vaporvee/loadsupport/mixin/MixinTitleScreen.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.vaporvee.loadsupport.mixin; - -import com.vaporvee.loadsupport.Constants; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.TitleScreen; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(TitleScreen.class) -public class MixinTitleScreen { - - @Inject(at = @At("HEAD"), method = "init()V") - private void init(CallbackInfo info) { - Constants.LOG.info("Mixin MC title Type: {}", Minecraft.getInstance().getVersionType()); - } -} \ No newline at end of file diff --git a/neoforge/src/main/java/com/vaporvee/loadsupport/mixin/WindowHideMixin.java b/neoforge/src/main/java/com/vaporvee/loadsupport/mixin/WindowHideMixin.java new file mode 100644 index 0000000..5038e39 --- /dev/null +++ b/neoforge/src/main/java/com/vaporvee/loadsupport/mixin/WindowHideMixin.java @@ -0,0 +1,23 @@ +package com.vaporvee.loadsupport.mixin; + +import com.mojang.blaze3d.platform.Window; +import com.vaporvee.loadsupport.Allocated; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Window.class) +public class WindowHideMixin { + @Inject( + method = "takeOverWindow", + at = @At("RETURN") + ) + private void onTakeOverWindow(CallbackInfoReturnable cir) { + if (!Allocated.enoughMemory) { + long w = cir.getReturnValue(); + GLFW.glfwHideWindow(w); + } + } +} diff --git a/neoforge/src/main/java/com/vaporvee/loadsupport/platform/LSConfigNeoForge.java b/neoforge/src/main/java/com/vaporvee/loadsupport/platform/LSConfigNeoForge.java index b6e13e9..11bcf36 100644 --- a/neoforge/src/main/java/com/vaporvee/loadsupport/platform/LSConfigNeoForge.java +++ b/neoforge/src/main/java/com/vaporvee/loadsupport/platform/LSConfigNeoForge.java @@ -5,6 +5,7 @@ import com.vaporvee.loadsupport.Config; import com.vaporvee.loadsupport.platform.services.IConfig; import me.shedaniel.autoconfig.AutoConfig; import me.shedaniel.autoconfig.serializer.Toml4jConfigSerializer; +import net.neoforged.neoforge.client.event.ScreenEvent; public class LSConfigNeoForge implements IConfig { public static Config config; @@ -13,6 +14,7 @@ public class LSConfigNeoForge implements IConfig { AutoConfig.register(Config.class, Toml4jConfigSerializer::new); config = AutoConfig.getConfigHolder(Config.class).getConfig(); CommonClass.checkConfig(config); + } @Override public Config getConfig() { diff --git a/neoforge/src/main/resources/loadsupport.neoforge.mixins.json b/neoforge/src/main/resources/loadsupport.neoforge.mixins.json index efe5eb7..38073da 100644 --- a/neoforge/src/main/resources/loadsupport.neoforge.mixins.json +++ b/neoforge/src/main/resources/loadsupport.neoforge.mixins.json @@ -5,7 +5,8 @@ "compatibilityLevel": "JAVA_21", "mixins": [], "client": [ - "MixinTitleScreen" + "MinecraftPauseMixin", + "WindowHideMixin" ], "server": [], "injectors": {