finished the ram checker and dialog. finished its implementation in neoforge

This commit is contained in:
2025-06-22 02:09:49 +02:00
parent 5dbf6dd823
commit 5e2ff74260
10 changed files with 111 additions and 40 deletions

View File

@@ -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("<span style=\"color:green\">%.1f</span>", config.minMemory);
String currentMemoryFormatted = String.format("<span style=\"color:red\">%.1f</span>", memoryInGB);
String heading = Constants.MOD_NAME + " - " + title;
String body = minMemoryText.replace("{minMemory}", minMemoryFormatted)
+ "<br><br>"
+ 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("<html><p style=\"width:200px\">"+ getWarningMessage()[1]+"</p></html>", JLabel.CENTER);
JButton exitButton = new JButton("OK");
JLabel message = new JLabel(
"<html><p style=\"width:290px; font-size:16px;\">" + warning[1] + "</p></html>",
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);
});
}

View File

@@ -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!");

View File

@@ -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";
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();
}
}
}

View File

@@ -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());
}
}

View File

@@ -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<Long> cir) {
if (!Allocated.enoughMemory) {
long w = cir.getReturnValue();
GLFW.glfwHideWindow(w);
}
}
}

View File

@@ -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() {

View File

@@ -5,7 +5,8 @@
"compatibilityLevel": "JAVA_21",
"mixins": [],
"client": [
"MixinTitleScreen"
"MinecraftPauseMixin",
"WindowHideMixin"
],
"server": [],
"injectors": {