From 8089deb17200cdb93282d4768bb63c697e8191d4 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Wed, 3 Sep 2025 02:51:19 +0200 Subject: [PATCH] Optimisations --- .../org/saturnclient/modules/ModManager.java | 32 ++- .../saturnclient/modules/mods/Keystrokes.java | 109 +++++--- .../modules/mods/mixins/RenderMixin.java | 2 +- .../saturnclient/saturnclient/auth/Auth.java | 1 - .../saturnclient/config/ConfigManager.java | 245 +++++------------- .../saturnclient/config/Property.java | 238 +++++++++-------- .../saturnclient/menus/HudEditor.java | 2 +- .../org/saturnclient/ui2/RenderScope.java | 120 +++++---- .../org/saturnclient/ui2/screens/ModMenu.java | 6 +- 9 files changed, 375 insertions(+), 380 deletions(-) diff --git a/src/main/java/org/saturnclient/modules/ModManager.java b/src/main/java/org/saturnclient/modules/ModManager.java index 459e661..b8a8f62 100644 --- a/src/main/java/org/saturnclient/modules/ModManager.java +++ b/src/main/java/org/saturnclient/modules/ModManager.java @@ -1,11 +1,14 @@ package org.saturnclient.modules; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import java.util.ArrayList; +import java.util.List; import org.saturnclient.modules.mods.*; public class ModManager { - public static Module[] MODS = { + public static final List ENABLED_MODS = new ArrayList<>(); + public static final Module[] ALL_MODS = { new Crosshair(), new AutoSprint(), new ArmorDisplay(), @@ -17,12 +20,31 @@ public class ModManager { }; public static void init() { + // Pre-filter enabled modules to avoid checking every tick + updateEnabledModules(); + ClientTickEvents.END_CLIENT_TICK.register(client -> { - for (Module m : MODS) { - if (m.isEnabled()) { - m.tick(); - } + // Only iterate over enabled modules + for (Module m : ENABLED_MODS) { + m.tick(); } }); } + + public static void updateEnabledModules() { + ENABLED_MODS.clear(); + for (Module m : ALL_MODS) { + if (m.isEnabled()) { + ENABLED_MODS.add(m); + } + } + } + + public static Module[] getAllMods() { + return ALL_MODS; + } + + public static void refreshEnabledModules() { + updateEnabledModules(); + } } diff --git a/src/main/java/org/saturnclient/modules/mods/Keystrokes.java b/src/main/java/org/saturnclient/modules/mods/Keystrokes.java index 44731e5..0eac3b0 100644 --- a/src/main/java/org/saturnclient/modules/mods/Keystrokes.java +++ b/src/main/java/org/saturnclient/modules/mods/Keystrokes.java @@ -13,6 +13,8 @@ public class Keystrokes extends Module implements HudMod { public static Property showMouse = Property.bool(true); public static Property showSpace = Property.bool(false); public static ModDimensions dimensions = new ModDimensions(78, 46); + + // Cache key states to avoid repeated calls private boolean w = false; private boolean a = false; private boolean s = false; @@ -21,27 +23,32 @@ public class Keystrokes extends Module implements HudMod { private boolean rmb = false; private boolean space = false; + // Cache dimensions to avoid recalculation + private int cachedHeight = 54; + private boolean dimensionsDirty = true; + private static Property clickBg = Property.color(0xFFCCCCCC); private static Property clickFg = Property.color(0xFFFFFFFF); public Keystrokes() { super(new ModuleDetails("Keystrokes", "keystrokes") - .description("Displays the keystrokes for movement") - .version("v0.1.0") - .tags("Utility"), + .description("Displays the keystrokes for movement") + .version("v0.1.0") + .tags("Utility"), - enabled.named("Enabled"), - showMouse.named("Show mouse clicks"), - showSpace.named("Show space clicks"), - dimensions.prop(), - clickFg.named("Clicked fg"), - clickBg.named("Clicked bg")); + enabled.named("Enabled"), + showMouse.named("Show mouse clicks"), + showSpace.named("Show space clicks"), + dimensions.prop(), + clickFg.named("Clicked fg"), + clickBg.named("Clicked bg")); dimensions.renderBackground = false; } - + @Override public void tick() { + // Cache key states to reduce method calls w = SaturnClient.client.options.forwardKey.isPressed(); a = SaturnClient.client.options.leftKey.isPressed(); s = SaturnClient.client.options.backKey.isPressed(); @@ -49,49 +56,67 @@ public class Keystrokes extends Module implements HudMod { lmb = SaturnClient.client.options.attackKey.isPressed(); rmb = SaturnClient.client.options.useKey.isPressed(); space = SaturnClient.client.options.jumpKey.isPressed(); + + // Mark dimensions as dirty if mouse or space visibility changed + if (dimensionsDirty) { + updateDimensions(); + dimensionsDirty = false; + } + } + + private void updateDimensions() { + cachedHeight = 54; // base height with padding considered + + if (showMouse.value) { + cachedHeight += 27; + } + + if (showSpace.value) { + cachedHeight += 22; + } + + dimensions.height = cachedHeight; } @Override public void renderDummy(RenderScope scope) { - dimensions.height = 54; // base height with padding considered + // Use cached dimensions + dimensions.height = cachedHeight; // WASD keys (3px padding between each key) - renderKey(scope, true, 'W', 27, 0); // Top center - renderKey(scope, false, 'A', 0, 27); // Bottom left - renderKey(scope, false, 'S', 27, 27); // Bottom center - renderKey(scope, false, 'D', 54, 27); // Bottom right + renderKey(scope, false, 'W', 27, 0); // Top center + renderKey(scope, false, 'A', 0, 27); // Bottom left + renderKey(scope, false, 'S', 27, 27); // Bottom center + renderKey(scope, false, 'D', 54, 27); // Bottom right if (showMouse.value) { - renderKeyM(scope, true, "LMB", 0, 54); // Below A/S/D - renderKeyM(scope, false, "RMB", 40, 54); // With 3px between - dimensions.height += 27; + renderKeyM(scope, false, "LMB", 0, 54); // Below A/S/D + renderKeyM(scope, false, "RMB", 40, 54); // With 3px between } if (showSpace.value) { - renderKeySpace(scope, false, 0, dimensions.height); - dimensions.height += 22; + renderKeySpace(scope, false, 0, cachedHeight - (showSpace.value ? 22 : 0)); } } @Override public void renderHud(RenderScope scope) { - dimensions.height = 54; // base height with padding considered + // Use cached dimensions + dimensions.height = cachedHeight; // WASD keys (3px padding between each key) - renderKey(scope, w, 'W', 27, 0); // Top center - renderKey(scope, a, 'A', 0, 27); // Bottom left - renderKey(scope, s, 'S', 27, 27); // Bottom center - renderKey(scope, d, 'D', 54, 27); // Bottom right + renderKey(scope, w, 'W', 27, 0); // Top center + renderKey(scope, a, 'A', 0, 27); // Bottom left + renderKey(scope, s, 'S', 27, 27); // Bottom center + renderKey(scope, d, 'D', 54, 27); // Bottom right if (showMouse.value) { - renderKeyM(scope, lmb, "LMB", 0, 54); // Below A/S/D - renderKeyM(scope, rmb, "RMB", 40, 54); // With 3px between - dimensions.height += 27; + renderKeyM(scope, lmb, "LMB", 0, 54); // Below A/S/D + renderKeyM(scope, rmb, "RMB", 40, 54); // With 3px between } if (showSpace.value) { - renderKeySpace(scope, space, 0, dimensions.height); - dimensions.height += 22; + renderKeySpace(scope, space, 0, cachedHeight - (showSpace.value ? 22 : 0)); } } @@ -99,29 +124,38 @@ public class Keystrokes extends Module implements HudMod { private void renderKeySpace(RenderScope scope, boolean isPressed, int x, int y) { int height = 19; - scope.drawRoundedRectangle(x, y, dimensions.width, height, dimensions.radius.value, isPressed ? clickBg.value : dimensions.bgColor.value); + int bgColor = isPressed ? clickBg.value : dimensions.bgColor.value; + int fgColor = isPressed ? clickFg.value : dimensions.fgColor.value; + + scope.drawRoundedRectangle(x, y, dimensions.width, height, dimensions.radius.value, bgColor); // A 30-pixel line centered vertically with 3px top padding int lineY = y + (height - 1) / 2; - scope.drawRect(x + (dimensions.width - 30) / 2, lineY, 30, 1, isPressed ? clickFg.value : dimensions.fgColor.value); + scope.drawRect(x + (dimensions.width - 30) / 2, lineY, 30, 1, fgColor); } private void renderKeyM(RenderScope scope, boolean isPressed, String c, int x, int y) { int width = 38, height = 24; - scope.drawRoundedRectangle(x, y, width, height, dimensions.radius.value, isPressed ? clickBg.value : dimensions.bgColor.value); + int bgColor = isPressed ? clickBg.value : dimensions.bgColor.value; + int fgColor = isPressed ? clickFg.value : dimensions.fgColor.value; + + scope.drawRoundedRectangle(x, y, width, height, dimensions.radius.value, bgColor); // Apply padding: 3px top and left -> add slight offset to x/y - scope.drawText(0.6f, c, x + 9, y + 7, dimensions.font.value, isPressed ? clickFg.value : dimensions.fgColor.value); + scope.drawText(0.6f, c, x + 9, y + 7, dimensions.font.value, fgColor); } private void renderKey(RenderScope scope, boolean isPressed, char c, int x, int y) { int size = 24; - scope.drawRoundedRectangle(x, y, size, size, dimensions.radius.value, isPressed ? clickBg.value : dimensions.bgColor.value); + int bgColor = isPressed ? clickBg.value : dimensions.bgColor.value; + int fgColor = isPressed ? clickFg.value : dimensions.fgColor.value; + + scope.drawRoundedRectangle(x, y, size, size, dimensions.radius.value, bgColor); // Center the character with 3px top padding - scope.drawText(0.6f, String.valueOf(c), x + 9, y + 7, dimensions.font.value, isPressed ? clickFg.value : dimensions.fgColor.value); + scope.drawText(0.6f, String.valueOf(c), x + 9, y + 7, dimensions.font.value, fgColor); } - + @Override public boolean isEnabled() { return enabled.value; @@ -135,5 +169,6 @@ public class Keystrokes extends Module implements HudMod { @Override public void setEnabled(boolean e) { enabled.value = e; + dimensionsDirty = true; } } \ No newline at end of file diff --git a/src/main/java/org/saturnclient/modules/mods/mixins/RenderMixin.java b/src/main/java/org/saturnclient/modules/mods/mixins/RenderMixin.java index e32f64f..a552698 100644 --- a/src/main/java/org/saturnclient/modules/mods/mixins/RenderMixin.java +++ b/src/main/java/org/saturnclient/modules/mods/mixins/RenderMixin.java @@ -29,7 +29,7 @@ public class RenderMixin { RenderScope renderScope = new RenderScope(context.getMatrices(), ((DrawContextAccessor) context).getVertexConsumers()); - for (org.saturnclient.modules.Module m : ModManager.MODS) { + for (org.saturnclient.modules.Module m : ModManager.ENABLED_MODS) { if (m instanceof HudMod && m.isEnabled()) { ModDimensions dim = ((HudMod) m).getDimensions(); diff --git a/src/main/java/org/saturnclient/saturnclient/auth/Auth.java b/src/main/java/org/saturnclient/saturnclient/auth/Auth.java index 5ecdf8c..13195d9 100644 --- a/src/main/java/org/saturnclient/saturnclient/auth/Auth.java +++ b/src/main/java/org/saturnclient/saturnclient/auth/Auth.java @@ -28,7 +28,6 @@ public class Auth { private static Thread pingThread; private static volatile boolean running = false; - @SuppressWarnings("resource") public static boolean authenticate() { // Register shutdown hook ONCE ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> close()); diff --git a/src/main/java/org/saturnclient/saturnclient/config/ConfigManager.java b/src/main/java/org/saturnclient/saturnclient/config/ConfigManager.java index a13ec16..4123bbf 100644 --- a/src/main/java/org/saturnclient/saturnclient/config/ConfigManager.java +++ b/src/main/java/org/saturnclient/saturnclient/config/ConfigManager.java @@ -1,223 +1,116 @@ package org.saturnclient.saturnclient.config; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; +import com.google.gson.*; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; import org.saturnclient.saturnclient.SaturnClient; public class ConfigManager { - private static File configFile = new File( - SaturnClient.client.runDirectory, - "saturn.json"); - private static Map>> properties = new HashMap<>(); + private static final File configFile = new File(SaturnClient.client.runDirectory, "saturn.json"); + private static final Map>> properties = new HashMap<>(); private static JsonObject cachedThemeJson = null; - private Map> currentMap; - private String namespace; + private final Map> currentMap; + private final String namespace; public ConfigManager(String namespace) { - currentMap = new LinkedHashMap<>(); + this.namespace = namespace; + this.currentMap = new LinkedHashMap<>(); properties.put(namespace, currentMap); System.out.println("Created namespace: " + namespace); } - public ConfigManager(ConfigManager config, String namespace) { - currentMap = new LinkedHashMap<>(); - Property>> namespaceProperty = Property.namespace(currentMap); - config.property(namespace, namespaceProperty); - // Update the parent's state - config.currentMap.put(namespace, namespaceProperty); + public ConfigManager(ConfigManager parent, String namespace) { + this.namespace = namespace; + this.currentMap = new LinkedHashMap<>(); + Property>> nsProp = Property.namespace(currentMap); + parent.property(namespace, nsProp); System.out.println("Created sub-namespace: " + namespace); } - public void sub(String namespace) { - Property>> namespaceProperty = Property.namespace(currentMap); - property(namespace, namespaceProperty); + public void sub(String name) { + property(name, Property.namespace(new LinkedHashMap<>())); } - // Generic method to store any type of property public Property property(String name, Property value) { currentMap.put(name, value); loadProp(name, value); return value; } - @SuppressWarnings("unchecked") - public void loadProp(String name, Property prop) { - if (cachedThemeJson != null) { - JsonElement element = cachedThemeJson.get(namespace); - if (element != null && element.isJsonObject()) { - JsonObject theme = element.getAsJsonObject(); - JsonElement value = theme.get(name); - if (value != null && prop.matchesJson(value)) { - switch (prop.getType()) { - case BOOLEAN: - ((Property) prop).setValue(value.getAsBoolean()); - break; - case INTEGER: - ((Property) prop).setValue(value.getAsInt()); - break; - case FLOAT: - ((Property) prop).setValue(value.getAsFloat()); - break; - case STRING: - ((Property) prop).setValue(value.getAsString()); - break; - case HEX: - ((Property) prop).setValue(value.getAsInt()); - break; - default: - break; - } - } + private void loadProp(String name, Property prop) { + JsonObject source = cachedThemeJson != null ? cachedThemeJson : loadAndCache(); + if (source == null) + return; + + JsonElement namespaceJson = source.get(namespace); + if (namespaceJson == null || !namespaceJson.isJsonObject()) + return; + + JsonElement value = namespaceJson.getAsJsonObject().get(name); + if (value != null) + prop.loadFromJson(value); + } + + private static JsonObject loadAndCache() { + try { + if (!configFile.exists()) { + Files.writeString(configFile.toPath(), "{}"); + return new JsonObject(); } - } else { - load(); + String json = Files.readString(configFile.toPath()); + cachedThemeJson = JsonParser.parseString(json).getAsJsonObject(); + return cachedThemeJson; + } catch (IOException e) { + SaturnClient.LOGGER.error("Error reading config file", e); + return null; } } public static void load() { - try { - SaturnClient.LOGGER.info("Starting to load config..."); - if (!configFile.exists()) { - configFile.createNewFile(); - Files.write(configFile.toPath(), "{}".getBytes()); + SaturnClient.LOGGER.info("Loading config..."); + JsonObject json = loadAndCache(); + if (json == null) + return; + + properties.forEach((namespace, map) -> { + JsonElement nsElement = json.get(namespace); + if (nsElement != null && nsElement.isJsonObject()) { + loadProperties(nsElement.getAsJsonObject(), map); } - - JsonObject jsonObject = JsonParser.parseString( - new String(Files.readAllBytes(configFile.toPath()))).getAsJsonObject(); - - for (String namespace : properties.keySet()) { - JsonElement configElement = jsonObject.get(namespace); - - if (configElement == null) - continue; - - JsonObject config = jsonObject.get(namespace).getAsJsonObject(); - - if (config == null) { - continue; - } - - Map> propertyMap = properties.get(namespace); - loadProperties(config, propertyMap); - } - } catch (IOException e) { - SaturnClient.LOGGER.error("Error reading the config file", e); - } + }); } - @SuppressWarnings("unchecked") - private static void loadProperties(JsonObject config, Map> propertyMap) { - for (String propertyName : propertyMap.keySet()) { - JsonElement c = config.get(propertyName); - - if (c == null) { - continue; - } - - Property p = propertyMap.get(propertyName); - if (p.matchesJson(c)) { - if (p.getType() == Property.PropertyType.NAMESPACE) { - // Handle nested namespace - JsonObject nestedConfig = c.getAsJsonObject(); - Map> nestedProperties = p.getNamespaceValue(); - loadProperties(nestedConfig, nestedProperties); - } else { - if (p.value instanceof Integer) { - ((Property) p).value = c.getAsInt(); - } else if (p.value instanceof String) { - ((Property) p).value = c.getAsString(); - } else if (p.value instanceof Float) { - ((Property) p).value = c.getAsFloat(); - } else if (p.value instanceof Boolean) { - ((Property) p).value = c.getAsBoolean(); - } else { - SaturnClient.LOGGER.warn( - "Unknown property type for: " + propertyName); - } - } - } else { - SaturnClient.LOGGER.warn( - "Property does not match JSON: " + propertyName); - } - } + private static void loadProperties(JsonObject json, Map> props) { + props.forEach((name, prop) -> { + JsonElement el = json.get(name); + if (el != null) + prop.loadFromJson(el); + }); } public static void save() { + SaturnClient.LOGGER.info("Saving config..."); + JsonObject root = new JsonObject(); + properties.forEach((namespace, map) -> { + JsonObject nsJson = new JsonObject(); + saveProperties(nsJson, map); + root.add(namespace, nsJson); + }); + try { - SaturnClient.LOGGER.info("Starting to save config..."); - - JsonObject jsonObject = new JsonObject(); - - // Iterate through all namespaces and their properties - for (String namespace : properties.keySet()) { - JsonObject namespaceConfig = new JsonObject(); - Map> propertyMap = properties.get(namespace); - - // Save properties for this namespace - saveProperties(namespaceConfig, propertyMap); - - // Add the namespace config to the main JSON object - jsonObject.add(namespace, namespaceConfig); - } - - // Format the json so it can easily be edited - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - String formattedJson = gson.toJson(jsonObject); - - // Write the JSON object to the config file - Files.write(configFile.toPath(), formattedJson.getBytes()); + String formatted = new GsonBuilder().setPrettyPrinting().create().toJson(root); + Files.writeString(configFile.toPath(), formatted); SaturnClient.LOGGER.info("Config saved successfully."); } catch (IOException e) { - SaturnClient.LOGGER.error("Error saving the config file", e); + SaturnClient.LOGGER.error("Error saving config file", e); } } - @SuppressWarnings("unchecked") - private static void saveProperties(JsonObject config, Map> propertyMap) { - // Iterate through each property in the namespace - for (String propertyName : propertyMap.keySet()) { - Property property = propertyMap.get(propertyName); - JsonElement propertyValue = null; - // Convert the property value based on its type - switch (property.getType()) { - case NAMESPACE: - // Handle nested namespace - JsonObject nestedConfig = new JsonObject(); - Map> nestedProperties = (Map>) property.value; - saveProperties(nestedConfig, nestedProperties); - propertyValue = nestedConfig; - break; - default: - if (property.value instanceof Integer) { - propertyValue = new JsonPrimitive((Integer) property.value); - } else if (property.value instanceof String) { - propertyValue = new JsonPrimitive((String) property.value); - } else if (property.value instanceof Float) { - propertyValue = new JsonPrimitive((Float) property.value); - } else if (property.value instanceof Boolean) { - propertyValue = new JsonPrimitive((Boolean) property.value); - } else { - SaturnClient.LOGGER.warn( - "Unknown property type for: " + propertyName); - } - break; - } - - if (propertyValue != null) { - config.add(propertyName, propertyValue); - } - } + private static void saveProperties(JsonObject json, Map> props) { + props.forEach((name, prop) -> json.add(name, prop.toJson())); } public Map> getProperties() { diff --git a/src/main/java/org/saturnclient/saturnclient/config/Property.java b/src/main/java/org/saturnclient/saturnclient/config/Property.java index 28ac3de..0a8aa01 100644 --- a/src/main/java/org/saturnclient/saturnclient/config/Property.java +++ b/src/main/java/org/saturnclient/saturnclient/config/Property.java @@ -6,6 +6,7 @@ import org.lwjgl.glfw.GLFW; import org.saturnclient.saturnclient.SaturnClient; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; public class Property { @@ -25,7 +26,7 @@ public class Property { public boolean isReset = false; private T defaultValue; private String[] availableValues; - private PropertyType type; + private final PropertyType type; private boolean wasPressedLastTick = false; private Property(T value, PropertyType type) { @@ -34,24 +35,19 @@ public class Property { this.type = type; } + // ---------- Factory Methods ---------- public static Property from(T value) { - if (value instanceof Boolean) { + if (value instanceof Boolean) return new Property<>(value, PropertyType.BOOLEAN); - } else if (value instanceof Integer) { + if (value instanceof Integer) return new Property<>(value, PropertyType.INTEGER); - } else if (value instanceof Float) { + if (value instanceof Float) return new Property<>(value, PropertyType.FLOAT); - } else if (value instanceof String) { + if (value instanceof String) return new Property<>(value, PropertyType.STRING); - } else if (valueIsNamespace(value)) { + if (valueIsNamespace(value)) return new Property<>(value, PropertyType.NAMESPACE); - } else { - return null; - } - } - - public Property copy() { - return new Property<>(this.value, this.type); + return null; } public static Property font(int value) { @@ -92,55 +88,37 @@ public class Property { return new Property<>(value, PropertyType.KEYBINDING); } + // ---------- Select Helpers ---------- public void next() { - if ((Integer) value < availableValues.length - 1) - setValue((Integer) value + 1); - else - setValue(0); + if (type == PropertyType.SELECT) { + int i = (Integer) value; + setValue((i < availableValues.length - 1) ? i + 1 : 0); + } } public void prev() { - if ((Integer) value > 0) - setValue((Integer) value - 1); - else - setValue(availableValues.length - 1); + if (type == PropertyType.SELECT) { + int i = (Integer) value; + setValue((i > 0) ? i - 1 : availableValues.length - 1); + } } public void setSelection(int selection) { - if (selection >= 0 && selection < availableValues.length && type == PropertyType.SELECT) { + if (type == PropertyType.SELECT && selection >= 0 && selection < availableValues.length) { setValue(selection); } } public String getSelection() { - if (type == PropertyType.SELECT) { - return availableValues[(Integer) value]; - } else { - return null; - } + return (type == PropertyType.SELECT) ? availableValues[(Integer) value] : null; } + // ---------- Lifecycle ---------- public void reset() { value = defaultValue; isReset = true; } - public int getHexString() { - if (value instanceof String) { - String str = (String) value; - if (str.startsWith("0x") || str.startsWith("0X")) { - try { - return Integer.parseInt(str.substring(2), 16); - } catch (NumberFormatException e) { - throw new IllegalStateException( - "Invalid hexadecimal integer format"); - } - } - } - throw new IllegalStateException( - "Property does not contain a valid hex integer"); - } - public PropertyType getType() { return type; } @@ -153,34 +131,93 @@ public class Property { throw new IllegalStateException("Property is not a namespace"); } - public boolean matchesJson(JsonElement element) { - if (element.isJsonPrimitive()) { - JsonPrimitive primitive = element.getAsJsonPrimitive(); - if (value instanceof Boolean && primitive.isBoolean()) - return true; - if (value instanceof Integer && primitive.isNumber()) - return true; - if (value instanceof Float && primitive.isNumber()) - return true; - if (value instanceof String && primitive.isString()) - return true; - if (type == PropertyType.HEX && primitive.isString()) - return true; - } else if (element.isJsonObject()) { - return isNamespace(value); + // ---------- JSON Serialization ---------- + /* + * BOOLEAN, + * INTEGER, + * FLOAT, + * STRING, + * HEX, + * NAMESPACE, + * SELECT, + * KEYBINDING, + */ + public JsonElement toJson() { + switch (type) { + case BOOLEAN: + return new JsonPrimitive((Boolean) value); + case INTEGER: + return new JsonPrimitive((Integer) value); + case FLOAT: + return new JsonPrimitive((Float) value); + case NAMESPACE: + JsonObject nested = new JsonObject(); + getNamespaceValue().forEach((k, v) -> nested.add(k, v.toJson())); + return nested; + case HEX: + return new JsonPrimitive(String.format("#%08X", (Integer) value)); + case KEYBINDING: + return new JsonPrimitive((Integer) value); + case SELECT: + return new JsonPrimitive((Integer) value); + default: + return new JsonPrimitive(String.valueOf(value)); } - return false; } + public void loadFromJson(JsonElement element) { + if (element == null) + return; + + switch (type) { + case BOOLEAN: + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isBoolean()) + setValue(element.getAsBoolean()); + break; + case INTEGER: + if (element.isJsonPrimitive()) { + JsonPrimitive p = element.getAsJsonPrimitive(); + if (p.isNumber()) + setValue(p.getAsInt()); + else if (p.isString()) + setValue(parseHexToInt(p.getAsString())); + } + break; + case FLOAT: + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) + setValue(element.getAsFloat()); + break; + case STRING: + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) + setValue(element.getAsString()); + break; + case HEX: + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) + setValue(parseHexToInt(element.getAsString())); + break; + case NAMESPACE: + if (element.isJsonObject()) { + JsonObject obj = element.getAsJsonObject(); + getNamespaceValue().forEach((k, v) -> v.loadFromJson(obj.get(k))); + } + break; + case SELECT: + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) + setSelection(element.getAsInt()); + break; + case KEYBINDING: + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) + setValue(element.getAsInt()); + break; + } + } + + // ---------- Utility ---------- @Override public String toString() { return String.valueOf(value); } - public boolean isNamespace(Object obj) { - return type == PropertyType.NAMESPACE && value instanceof Map; - } - public static boolean valueIsNamespace(Object obj) { return obj instanceof Map; } @@ -200,59 +237,44 @@ public class Property { return new NamedProperty<>(name, this); } + // ---------- Keybindings ---------- public boolean isKeyPressed() { - return (Integer) value == -1 ? false - : GLFW.glfwGetKey(SaturnClient.client.getWindow().getHandle(), - (Integer) (Object) value) == GLFW.GLFW_PRESS && SaturnClient.client.currentScreen == null; + return (Integer) value != -1 && + GLFW.glfwGetKey(SaturnClient.client.getWindow().getHandle(), (Integer) value) == GLFW.GLFW_PRESS && + SaturnClient.client.currentScreen == null; } public boolean wasKeyPressed() { - boolean isPressed = this.isKeyPressed(); - wasPressedLastTick = isPressed && !wasPressedLastTick; - return wasPressedLastTick; - } - - @SuppressWarnings("unchecked") - public void load(String name, JsonElement element) { - if (element != null && element.isJsonObject()) { - JsonElement value = element.getAsJsonObject().get(name); - if (value != null) { - switch (this.getType()) { - case BOOLEAN: - ((Property) this).setValue(value.getAsBoolean()); - break; - case INTEGER: - JsonPrimitive primitive = value.getAsJsonPrimitive(); - if (primitive.isNumber()) - ((Property) this).setValue(value.getAsInt()); - else if (primitive.isString()) - ((Property) this).setValue(parseHexToInt(value.getAsString())); - break; - case FLOAT: - ((Property) this).setValue(value.getAsFloat()); - break; - case STRING: - ((Property) this).setValue(value.getAsString()); - break; - case HEX: - ((Property) this).setValue(parseHexToInt(value.getAsString())); - break; - default: - break; - } - } - } + boolean pressed = isKeyPressed(); + boolean result = pressed && !wasPressedLastTick; + wasPressedLastTick = pressed; + return result; } + // ---------- HEX ---------- public static int parseHexToInt(String hex) { - hex = hex.replaceAll("#", ""); - - if (hex.length() == 6) { + hex = hex.replace("#", ""); + if (hex.length() == 6) hex = "FF" + hex; - } else if (hex.length() != 8) { - throw new IllegalArgumentException("Hex string must be 6 or 8 characters long"); - } - + if (hex.length() != 8) + throw new IllegalArgumentException("Hex must be 6 or 8 chars long, got \'" + hex + "\'"); return (int) Long.parseLong(hex, 16); } + + // Misc + public Property copy() { + return new Property<>(this.value, this.type); + } + + public void load(String name, JsonElement element) { + if (element != null && element.isJsonObject()) { + load(name, element.getAsJsonObject()); + } + } + + public void load(String name, JsonObject element) { + JsonElement value = element.get(name); + if (value != null) + this.loadFromJson(value); + } } diff --git a/src/main/java/org/saturnclient/saturnclient/menus/HudEditor.java b/src/main/java/org/saturnclient/saturnclient/menus/HudEditor.java index 0973d16..95fd28c 100644 --- a/src/main/java/org/saturnclient/saturnclient/menus/HudEditor.java +++ b/src/main/java/org/saturnclient/saturnclient/menus/HudEditor.java @@ -26,7 +26,7 @@ public class HudEditor extends Screen { public HudEditor() { super(Text.literal("HUD Editor")); - for (Module m : ModManager.MODS) { + for (Module m : ModManager.ENABLED_MODS) { if (m.isEnabled() && m instanceof HudMod) { hudMods.add((HudMod) m); } diff --git a/src/main/java/org/saturnclient/ui2/RenderScope.java b/src/main/java/org/saturnclient/ui2/RenderScope.java index cdd486c..8954e05 100644 --- a/src/main/java/org/saturnclient/ui2/RenderScope.java +++ b/src/main/java/org/saturnclient/ui2/RenderScope.java @@ -58,13 +58,15 @@ public class RenderScope { int newAlpha = (opacity >>> 24) & 0xFF; int mixedAlpha = (originalAlpha * newAlpha) / 255; return (mixedAlpha << 24) | (color & 0x00FFFFFF); - } + } public void setRenderLayer(Function renderLayers) { // this.renderLayers = renderLayers; } public void drawRect(int x, int y, int width, int height, int color) { + if (color == 0) + return; color = getColor(color); Matrix4f matrix4f = this.matrices.peek().getPositionMatrix(); @@ -98,6 +100,8 @@ public class RenderScope { } public void drawText(float scale, String text, int x, int y, int font, int color) { + if (color == 0) + return; if (font == 0) { scale *= 2; } @@ -108,7 +112,8 @@ public class RenderScope { matrices.translate(x, y + (i * Fonts.getHeight()), 0); matrices.scale(scale, scale, 1.0f); TextRenderer textRenderer = SaturnClient.client.textRenderer; - textRenderer.draw(Fonts.setFont(line, Fonts.getFont(font)), 0, font == 0 ? 1: 7, color, false, this.matrices.peek().getPositionMatrix(), + textRenderer.draw(Fonts.setFont(line, Fonts.getFont(font)), 0, font == 0 ? 1 : 7, color, false, + this.matrices.peek().getPositionMatrix(), this.vertexConsumers, TextLayerType.NORMAL, 0, 15728880); matrices.pop(); i++; @@ -118,19 +123,19 @@ public class RenderScope { private void drawRoundedCorner(int width, int height, int radius, int color) { int w = width * 20; int h = height * 20; - + for (int y = 0; y < h; y++) { int startX = 0; - + if (y < radius) { double dy = radius - y - 0.5; double dx = Math.sqrt(Math.max(0, radius * radius - dy * dy)); startX = radius - (int) dx; } - + this.drawRect(startX, y, w - startX, 1, color); } - } + } private void drawRoundedSide(int cornerWidth, int cornerHeight, int radius, int color) { // Top @@ -159,6 +164,8 @@ public class RenderScope { } public void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color) { + if (color == 0) + return; radius = Math.min(radius, Math.min(width, height)); int cornerWidth = width / 2; int cornerHeight = height / 2; @@ -183,27 +190,35 @@ public class RenderScope { public int getScaledWindowWidth() { return SaturnClient.client.getWindow().getScaledWidth(); } - + public int getScaledWindowHeight() { - return SaturnClient.client.getWindow().getScaledHeight(); + return SaturnClient.client.getWindow().getScaledHeight(); } + public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int color) { - this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color); + this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color); } public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height) { - this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height); + this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height); } - public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWith, int regionHeight, int textureWidth, int textureHeight) { - this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1); + public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWith, + int regionHeight, int textureWidth, int textureHeight) { + this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1); } - public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWidth, int regionHeight, int textureWidth, int textureHeight, int color) { - this.drawTexturedQuad(sprite, x, x + width, y, y + height, (u + 0.0F) / (float)textureWidth, (u + (float)regionWidth) / (float)textureWidth, (v + 0.0F) / (float)textureHeight, (v + (float)regionHeight) / (float)textureHeight, color); + public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWidth, + int regionHeight, int textureWidth, int textureHeight, int color) { + this.drawTexturedQuad(sprite, x, x + width, y, y + height, (u + 0.0F) / (float) textureWidth, + (u + (float) regionWidth) / (float) textureWidth, (v + 0.0F) / (float) textureHeight, + (v + (float) regionHeight) / (float) textureHeight, color); } - private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2, float u1, float u2, float v1, float v2, int color) { + private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2, float u1, float u2, float v1, + float v2, int color) { + if (color == 0) + return; x1 *= 4; x2 *= 4; y1 *= 4; @@ -213,44 +228,45 @@ public class RenderScope { matrices.push(); matrices.scale(0.25f, 0.25f, 1.0f); RenderSystem.setShaderTexture(0, sprite); - RenderLayer renderLayer = (RenderLayer)RenderLayer.getGuiTextured(sprite); + RenderLayer renderLayer = (RenderLayer) RenderLayer.getGuiTextured(sprite); Matrix4f matrix4f = this.matrices.peek().getPositionMatrix(); VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(renderLayer); - vertexConsumer.vertex(matrix4f, (float)x1, (float)y1, 0.0F).texture(u1, v1).color(color); - vertexConsumer.vertex(matrix4f, (float)x1, (float)y2, 0.0F).texture(u1, v2).color(color); - vertexConsumer.vertex(matrix4f, (float)x2, (float)y2, 0.0F).texture(u2, v2).color(color); - vertexConsumer.vertex(matrix4f, (float)x2, (float)y1, 0.0F).texture(u2, v1).color(color); + vertexConsumer.vertex(matrix4f, (float) x1, (float) y1, 0.0F).texture(u1, v1).color(color); + vertexConsumer.vertex(matrix4f, (float) x1, (float) y2, 0.0F).texture(u1, v2).color(color); + vertexConsumer.vertex(matrix4f, (float) x2, (float) y2, 0.0F).texture(u2, v2).color(color); + vertexConsumer.vertex(matrix4f, (float) x2, (float) y1, 0.0F).texture(u2, v1).color(color); matrices.pop(); } public void enableScissor(int x1, int y1, int x2, int y2) { - ScreenRect screenRect = (new ScreenRect(x1, y1, x2 - x1, y2 - y1)).transform(this.matrices.peek().getPositionMatrix()); + ScreenRect screenRect = (new ScreenRect(x1, y1, x2 - x1, y2 - y1)) + .transform(this.matrices.peek().getPositionMatrix()); this.setScissor(this.scissorStack.push(screenRect)); } - + public void disableScissor() { this.setScissor(this.scissorStack.pop()); } - + public boolean scissorContains(int x, int y) { return this.scissorStack.containsPoint(x, y); } - + private void setScissor(@Nullable ScreenRect rect) { this.draw(); if (rect != null) { - Window window = SaturnClient.client.getWindow(); - int i = window.getFramebufferHeight(); - double d = window.getScaleFactor(); - double e = (double)rect.getLeft() * d; - double f = (double)i - (double)rect.getBottom() * d; - double g = (double)rect.width() * d; - double h = (double)rect.height() * d; - RenderSystem.enableScissor((int)e, (int)f, Math.max(0, (int)g), Math.max(0, (int)h)); + Window window = SaturnClient.client.getWindow(); + int i = window.getFramebufferHeight(); + double d = window.getScaleFactor(); + double e = (double) rect.getLeft() * d; + double f = (double) i - (double) rect.getBottom() * d; + double g = (double) rect.width() * d; + double h = (double) rect.height() * d; + RenderSystem.enableScissor((int) e, (int) f, Math.max(0, (int) g), Math.max(0, (int) h)); } else { - RenderSystem.disableScissor(); + RenderSystem.disableScissor(); } - + } public void draw() { @@ -260,7 +276,7 @@ public class RenderScope { public void draw(Consumer drawer) { drawer.accept(this.vertexConsumers); this.vertexConsumers.draw(); - } + } static class ScissorStack { private final Deque stack = new ArrayDeque<>(); @@ -268,7 +284,8 @@ public class RenderScope { public ScreenRect push(ScreenRect p_281812_) { ScreenRect screenrectangle = this.stack.peekLast(); if (screenrectangle != null) { - ScreenRect screenrectangle1 = Objects.requireNonNullElse(p_281812_.intersection(screenrectangle), ScreenRect.empty()); + ScreenRect screenrectangle1 = Objects.requireNonNullElse(p_281812_.intersection(screenrectangle), + ScreenRect.empty()); this.stack.addLast(screenrectangle1); return screenrectangle1; } else { @@ -309,47 +326,51 @@ public class RenderScope { } public void drawItemWithoutEntity(ItemStack stack, int x, int y, int seed) { - this.drawItem((LivingEntity)null, SaturnClient.client.world, stack, x, y, seed); + this.drawItem((LivingEntity) null, SaturnClient.client.world, stack, x, y, seed); } public void drawItem(LivingEntity entity, ItemStack stack, int x, int y, int seed) { this.drawItem(entity, entity.getWorld(), stack, x, y, seed); } - private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed) { + private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, + int seed) { this.drawItem(entity, world, stack, x, y, seed, 0); } - private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed, int z) { + private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed, + int z) { if (!stack.isEmpty()) { - SaturnClient.client.getItemModelManager().update(this.itemRenderState, stack, ModelTransformationMode.GUI, false, world, entity, seed); + SaturnClient.client.getItemModelManager().update(this.itemRenderState, stack, ModelTransformationMode.GUI, + false, world, entity, seed); this.matrices.push(); - this.matrices.translate((float)(x + 8), (float)(y + 8), (float)(150 + (this.itemRenderState.hasDepth() ? z : 0))); + this.matrices.translate((float) (x + 8), (float) (y + 8), + (float) (150 + (this.itemRenderState.hasDepth() ? z : 0))); try { this.matrices.scale(16.0F, -16.0F, 16.0F); boolean bl = !this.itemRenderState.isSideLit(); if (bl) { - this.draw(); - DiffuseLighting.disableGuiDepthLighting(); + this.draw(); + DiffuseLighting.disableGuiDepthLighting(); } this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.DEFAULT_UV); this.draw(); if (bl) { - DiffuseLighting.enableGuiDepthLighting(); + DiffuseLighting.enableGuiDepthLighting(); } } catch (Throwable var11) { CrashReport crashReport = CrashReport.create(var11, "Rendering item"); CrashReportSection crashReportSection = crashReport.addElement("Item being rendered"); crashReportSection.add("Item Type", () -> { - return String.valueOf(stack.getItem()); + return String.valueOf(stack.getItem()); }); crashReportSection.add("Item Components", () -> { - return String.valueOf(stack.getComponents()); + return String.valueOf(stack.getComponents()); }); crashReportSection.add("Item Foil", () -> { - return String.valueOf(stack.hasGlint()); + return String.valueOf(stack.hasGlint()); }); throw new CrashException(crashReport); } @@ -363,8 +384,11 @@ public class RenderScope { } public void drawSpriteStretched(Sprite sprite, int x, int y, int width, int height, int color) { + if (color == 0) + return; if (width != 0 && height != 0) { - this.drawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV(), color); + this.drawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height, sprite.getMinU(), sprite.getMaxU(), + sprite.getMinV(), sprite.getMaxV(), color); } } } diff --git a/src/main/java/org/saturnclient/ui2/screens/ModMenu.java b/src/main/java/org/saturnclient/ui2/screens/ModMenu.java index b69ee5d..8b414a6 100644 --- a/src/main/java/org/saturnclient/ui2/screens/ModMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/ModMenu.java @@ -23,8 +23,8 @@ public class ModMenu extends SaturnScreen { int row = 0; int col = 0; - - for (Module mod : ModManager.MODS) { + + for (Module mod : ModManager.ALL_MODS) { scroll.draw(new SaturnModule(mod).position((160 + g) * col, (50 + g) * row)); if (col == 2) { @@ -36,7 +36,7 @@ public class ModMenu extends SaturnScreen { } int scrollWidth = 480 + 10 + (g * 2) + (p * 2); - + draw(scroll.dimensions(scrollWidth, 350).center(width, height)); draw(new Sidebar(0, this::close).centerOffset(width, height, -(scrollWidth / 2 + 20), 0));