Optimisations
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
package org.saturnclient.modules;
|
package org.saturnclient.modules;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.saturnclient.modules.mods.*;
|
import org.saturnclient.modules.mods.*;
|
||||||
|
|
||||||
public class ModManager {
|
public class ModManager {
|
||||||
public static Module[] MODS = {
|
public static final List<Module> ENABLED_MODS = new ArrayList<>();
|
||||||
|
public static final Module[] ALL_MODS = {
|
||||||
new Crosshair(),
|
new Crosshair(),
|
||||||
new AutoSprint(),
|
new AutoSprint(),
|
||||||
new ArmorDisplay(),
|
new ArmorDisplay(),
|
||||||
@@ -17,12 +20,31 @@ public class ModManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
|
// Pre-filter enabled modules to avoid checking every tick
|
||||||
|
updateEnabledModules();
|
||||||
|
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
||||||
for (Module m : MODS) {
|
// Only iterate over enabled modules
|
||||||
if (m.isEnabled()) {
|
for (Module m : ENABLED_MODS) {
|
||||||
m.tick();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ public class Keystrokes extends Module implements HudMod {
|
|||||||
public static Property<Boolean> showMouse = Property.bool(true);
|
public static Property<Boolean> showMouse = Property.bool(true);
|
||||||
public static Property<Boolean> showSpace = Property.bool(false);
|
public static Property<Boolean> showSpace = Property.bool(false);
|
||||||
public static ModDimensions dimensions = new ModDimensions(78, 46);
|
public static ModDimensions dimensions = new ModDimensions(78, 46);
|
||||||
|
|
||||||
|
// Cache key states to avoid repeated calls
|
||||||
private boolean w = false;
|
private boolean w = false;
|
||||||
private boolean a = false;
|
private boolean a = false;
|
||||||
private boolean s = false;
|
private boolean s = false;
|
||||||
@@ -21,27 +23,32 @@ public class Keystrokes extends Module implements HudMod {
|
|||||||
private boolean rmb = false;
|
private boolean rmb = false;
|
||||||
private boolean space = false;
|
private boolean space = false;
|
||||||
|
|
||||||
|
// Cache dimensions to avoid recalculation
|
||||||
|
private int cachedHeight = 54;
|
||||||
|
private boolean dimensionsDirty = true;
|
||||||
|
|
||||||
private static Property<Integer> clickBg = Property.color(0xFFCCCCCC);
|
private static Property<Integer> clickBg = Property.color(0xFFCCCCCC);
|
||||||
private static Property<Integer> clickFg = Property.color(0xFFFFFFFF);
|
private static Property<Integer> clickFg = Property.color(0xFFFFFFFF);
|
||||||
|
|
||||||
public Keystrokes() {
|
public Keystrokes() {
|
||||||
super(new ModuleDetails("Keystrokes", "keystrokes")
|
super(new ModuleDetails("Keystrokes", "keystrokes")
|
||||||
.description("Displays the keystrokes for movement")
|
.description("Displays the keystrokes for movement")
|
||||||
.version("v0.1.0")
|
.version("v0.1.0")
|
||||||
.tags("Utility"),
|
.tags("Utility"),
|
||||||
|
|
||||||
enabled.named("Enabled"),
|
enabled.named("Enabled"),
|
||||||
showMouse.named("Show mouse clicks"),
|
showMouse.named("Show mouse clicks"),
|
||||||
showSpace.named("Show space clicks"),
|
showSpace.named("Show space clicks"),
|
||||||
dimensions.prop(),
|
dimensions.prop(),
|
||||||
clickFg.named("Clicked fg"),
|
clickFg.named("Clicked fg"),
|
||||||
clickBg.named("Clicked bg"));
|
clickBg.named("Clicked bg"));
|
||||||
|
|
||||||
dimensions.renderBackground = false;
|
dimensions.renderBackground = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
// Cache key states to reduce method calls
|
||||||
w = SaturnClient.client.options.forwardKey.isPressed();
|
w = SaturnClient.client.options.forwardKey.isPressed();
|
||||||
a = SaturnClient.client.options.leftKey.isPressed();
|
a = SaturnClient.client.options.leftKey.isPressed();
|
||||||
s = SaturnClient.client.options.backKey.isPressed();
|
s = SaturnClient.client.options.backKey.isPressed();
|
||||||
@@ -49,49 +56,67 @@ public class Keystrokes extends Module implements HudMod {
|
|||||||
lmb = SaturnClient.client.options.attackKey.isPressed();
|
lmb = SaturnClient.client.options.attackKey.isPressed();
|
||||||
rmb = SaturnClient.client.options.useKey.isPressed();
|
rmb = SaturnClient.client.options.useKey.isPressed();
|
||||||
space = SaturnClient.client.options.jumpKey.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
|
@Override
|
||||||
public void renderDummy(RenderScope scope) {
|
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)
|
// WASD keys (3px padding between each key)
|
||||||
renderKey(scope, true, 'W', 27, 0); // Top center
|
renderKey(scope, false, 'W', 27, 0); // Top center
|
||||||
renderKey(scope, false, 'A', 0, 27); // Bottom left
|
renderKey(scope, false, 'A', 0, 27); // Bottom left
|
||||||
renderKey(scope, false, 'S', 27, 27); // Bottom center
|
renderKey(scope, false, 'S', 27, 27); // Bottom center
|
||||||
renderKey(scope, false, 'D', 54, 27); // Bottom right
|
renderKey(scope, false, 'D', 54, 27); // Bottom right
|
||||||
|
|
||||||
if (showMouse.value) {
|
if (showMouse.value) {
|
||||||
renderKeyM(scope, true, "LMB", 0, 54); // Below A/S/D
|
renderKeyM(scope, false, "LMB", 0, 54); // Below A/S/D
|
||||||
renderKeyM(scope, false, "RMB", 40, 54); // With 3px between
|
renderKeyM(scope, false, "RMB", 40, 54); // With 3px between
|
||||||
dimensions.height += 27;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showSpace.value) {
|
if (showSpace.value) {
|
||||||
renderKeySpace(scope, false, 0, dimensions.height);
|
renderKeySpace(scope, false, 0, cachedHeight - (showSpace.value ? 22 : 0));
|
||||||
dimensions.height += 22;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderHud(RenderScope scope) {
|
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)
|
// WASD keys (3px padding between each key)
|
||||||
renderKey(scope, w, 'W', 27, 0); // Top center
|
renderKey(scope, w, 'W', 27, 0); // Top center
|
||||||
renderKey(scope, a, 'A', 0, 27); // Bottom left
|
renderKey(scope, a, 'A', 0, 27); // Bottom left
|
||||||
renderKey(scope, s, 'S', 27, 27); // Bottom center
|
renderKey(scope, s, 'S', 27, 27); // Bottom center
|
||||||
renderKey(scope, d, 'D', 54, 27); // Bottom right
|
renderKey(scope, d, 'D', 54, 27); // Bottom right
|
||||||
|
|
||||||
if (showMouse.value) {
|
if (showMouse.value) {
|
||||||
renderKeyM(scope, lmb, "LMB", 0, 54); // Below A/S/D
|
renderKeyM(scope, lmb, "LMB", 0, 54); // Below A/S/D
|
||||||
renderKeyM(scope, rmb, "RMB", 40, 54); // With 3px between
|
renderKeyM(scope, rmb, "RMB", 40, 54); // With 3px between
|
||||||
dimensions.height += 27;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showSpace.value) {
|
if (showSpace.value) {
|
||||||
renderKeySpace(scope, space, 0, dimensions.height);
|
renderKeySpace(scope, space, 0, cachedHeight - (showSpace.value ? 22 : 0));
|
||||||
dimensions.height += 22;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,29 +124,38 @@ public class Keystrokes extends Module implements HudMod {
|
|||||||
|
|
||||||
private void renderKeySpace(RenderScope scope, boolean isPressed, int x, int y) {
|
private void renderKeySpace(RenderScope scope, boolean isPressed, int x, int y) {
|
||||||
int height = 19;
|
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
|
// A 30-pixel line centered vertically with 3px top padding
|
||||||
int lineY = y + (height - 1) / 2;
|
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) {
|
private void renderKeyM(RenderScope scope, boolean isPressed, String c, int x, int y) {
|
||||||
int width = 38, height = 24;
|
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
|
// 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) {
|
private void renderKey(RenderScope scope, boolean isPressed, char c, int x, int y) {
|
||||||
int size = 24;
|
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
|
// 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
|
@Override
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return enabled.value;
|
return enabled.value;
|
||||||
@@ -135,5 +169,6 @@ public class Keystrokes extends Module implements HudMod {
|
|||||||
@Override
|
@Override
|
||||||
public void setEnabled(boolean e) {
|
public void setEnabled(boolean e) {
|
||||||
enabled.value = e;
|
enabled.value = e;
|
||||||
|
dimensionsDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ public class RenderMixin {
|
|||||||
RenderScope renderScope = new RenderScope(context.getMatrices(),
|
RenderScope renderScope = new RenderScope(context.getMatrices(),
|
||||||
((DrawContextAccessor) context).getVertexConsumers());
|
((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()) {
|
if (m instanceof HudMod && m.isEnabled()) {
|
||||||
ModDimensions dim = ((HudMod) m).getDimensions();
|
ModDimensions dim = ((HudMod) m).getDimensions();
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ public class Auth {
|
|||||||
private static Thread pingThread;
|
private static Thread pingThread;
|
||||||
private static volatile boolean running = false;
|
private static volatile boolean running = false;
|
||||||
|
|
||||||
@SuppressWarnings("resource")
|
|
||||||
public static boolean authenticate() {
|
public static boolean authenticate() {
|
||||||
// Register shutdown hook ONCE
|
// Register shutdown hook ONCE
|
||||||
ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> close());
|
ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> close());
|
||||||
|
|||||||
@@ -1,223 +1,116 @@
|
|||||||
package org.saturnclient.saturnclient.config;
|
package org.saturnclient.saturnclient.config;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.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 java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.saturnclient.saturnclient.SaturnClient;
|
import org.saturnclient.saturnclient.SaturnClient;
|
||||||
|
|
||||||
public class ConfigManager {
|
public class ConfigManager {
|
||||||
private static File configFile = new File(
|
private static final File configFile = new File(SaturnClient.client.runDirectory, "saturn.json");
|
||||||
SaturnClient.client.runDirectory,
|
private static final Map<String, Map<String, Property<?>>> properties = new HashMap<>();
|
||||||
"saturn.json");
|
|
||||||
private static Map<String, Map<String, Property<?>>> properties = new HashMap<>();
|
|
||||||
private static JsonObject cachedThemeJson = null;
|
private static JsonObject cachedThemeJson = null;
|
||||||
|
|
||||||
private Map<String, Property<?>> currentMap;
|
private final Map<String, Property<?>> currentMap;
|
||||||
private String namespace;
|
private final String namespace;
|
||||||
|
|
||||||
public ConfigManager(String namespace) {
|
public ConfigManager(String namespace) {
|
||||||
currentMap = new LinkedHashMap<>();
|
this.namespace = namespace;
|
||||||
|
this.currentMap = new LinkedHashMap<>();
|
||||||
properties.put(namespace, currentMap);
|
properties.put(namespace, currentMap);
|
||||||
System.out.println("Created namespace: " + namespace);
|
System.out.println("Created namespace: " + namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigManager(ConfigManager config, String namespace) {
|
public ConfigManager(ConfigManager parent, String namespace) {
|
||||||
currentMap = new LinkedHashMap<>();
|
this.namespace = namespace;
|
||||||
Property<Map<String, Property<?>>> namespaceProperty = Property.namespace(currentMap);
|
this.currentMap = new LinkedHashMap<>();
|
||||||
config.property(namespace, namespaceProperty);
|
Property<Map<String, Property<?>>> nsProp = Property.namespace(currentMap);
|
||||||
// Update the parent's state
|
parent.property(namespace, nsProp);
|
||||||
config.currentMap.put(namespace, namespaceProperty);
|
|
||||||
System.out.println("Created sub-namespace: " + namespace);
|
System.out.println("Created sub-namespace: " + namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sub(String namespace) {
|
public void sub(String name) {
|
||||||
Property<Map<String, Property<?>>> namespaceProperty = Property.namespace(currentMap);
|
property(name, Property.namespace(new LinkedHashMap<>()));
|
||||||
property(namespace, namespaceProperty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic method to store any type of property
|
|
||||||
public <T> Property<T> property(String name, Property<T> value) {
|
public <T> Property<T> property(String name, Property<T> value) {
|
||||||
currentMap.put(name, value);
|
currentMap.put(name, value);
|
||||||
loadProp(name, value);
|
loadProp(name, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
private <T> void loadProp(String name, Property<T> prop) {
|
||||||
public <T> void loadProp(String name, Property<T> prop) {
|
JsonObject source = cachedThemeJson != null ? cachedThemeJson : loadAndCache();
|
||||||
if (cachedThemeJson != null) {
|
if (source == null)
|
||||||
JsonElement element = cachedThemeJson.get(namespace);
|
return;
|
||||||
if (element != null && element.isJsonObject()) {
|
|
||||||
JsonObject theme = element.getAsJsonObject();
|
JsonElement namespaceJson = source.get(namespace);
|
||||||
JsonElement value = theme.get(name);
|
if (namespaceJson == null || !namespaceJson.isJsonObject())
|
||||||
if (value != null && prop.matchesJson(value)) {
|
return;
|
||||||
switch (prop.getType()) {
|
|
||||||
case BOOLEAN:
|
JsonElement value = namespaceJson.getAsJsonObject().get(name);
|
||||||
((Property<Boolean>) prop).setValue(value.getAsBoolean());
|
if (value != null)
|
||||||
break;
|
prop.loadFromJson(value);
|
||||||
case INTEGER:
|
}
|
||||||
((Property<Integer>) prop).setValue(value.getAsInt());
|
|
||||||
break;
|
private static JsonObject loadAndCache() {
|
||||||
case FLOAT:
|
try {
|
||||||
((Property<Float>) prop).setValue(value.getAsFloat());
|
if (!configFile.exists()) {
|
||||||
break;
|
Files.writeString(configFile.toPath(), "{}");
|
||||||
case STRING:
|
return new JsonObject();
|
||||||
((Property<String>) prop).setValue(value.getAsString());
|
|
||||||
break;
|
|
||||||
case HEX:
|
|
||||||
((Property<Integer>) prop).setValue(value.getAsInt());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
String json = Files.readString(configFile.toPath());
|
||||||
load();
|
cachedThemeJson = JsonParser.parseString(json).getAsJsonObject();
|
||||||
|
return cachedThemeJson;
|
||||||
|
} catch (IOException e) {
|
||||||
|
SaturnClient.LOGGER.error("Error reading config file", e);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void load() {
|
public static void load() {
|
||||||
try {
|
SaturnClient.LOGGER.info("Loading config...");
|
||||||
SaturnClient.LOGGER.info("Starting to load config...");
|
JsonObject json = loadAndCache();
|
||||||
if (!configFile.exists()) {
|
if (json == null)
|
||||||
configFile.createNewFile();
|
return;
|
||||||
Files.write(configFile.toPath(), "{}".getBytes());
|
|
||||||
|
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<String, Property<?>> 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 json, Map<String, Property<?>> props) {
|
||||||
private static void loadProperties(JsonObject config, Map<String, Property<?>> propertyMap) {
|
props.forEach((name, prop) -> {
|
||||||
for (String propertyName : propertyMap.keySet()) {
|
JsonElement el = json.get(name);
|
||||||
JsonElement c = config.get(propertyName);
|
if (el != null)
|
||||||
|
prop.loadFromJson(el);
|
||||||
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<String, Property<?>> nestedProperties = p.getNamespaceValue();
|
|
||||||
loadProperties(nestedConfig, nestedProperties);
|
|
||||||
} else {
|
|
||||||
if (p.value instanceof Integer) {
|
|
||||||
((Property<Integer>) p).value = c.getAsInt();
|
|
||||||
} else if (p.value instanceof String) {
|
|
||||||
((Property<String>) p).value = c.getAsString();
|
|
||||||
} else if (p.value instanceof Float) {
|
|
||||||
((Property<Float>) p).value = c.getAsFloat();
|
|
||||||
} else if (p.value instanceof Boolean) {
|
|
||||||
((Property<Boolean>) p).value = c.getAsBoolean();
|
|
||||||
} else {
|
|
||||||
SaturnClient.LOGGER.warn(
|
|
||||||
"Unknown property type for: " + propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SaturnClient.LOGGER.warn(
|
|
||||||
"Property does not match JSON: " + propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void save() {
|
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 {
|
try {
|
||||||
SaturnClient.LOGGER.info("Starting to save config...");
|
String formatted = new GsonBuilder().setPrettyPrinting().create().toJson(root);
|
||||||
|
Files.writeString(configFile.toPath(), formatted);
|
||||||
JsonObject jsonObject = new JsonObject();
|
|
||||||
|
|
||||||
// Iterate through all namespaces and their properties
|
|
||||||
for (String namespace : properties.keySet()) {
|
|
||||||
JsonObject namespaceConfig = new JsonObject();
|
|
||||||
Map<String, Property<?>> 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());
|
|
||||||
SaturnClient.LOGGER.info("Config saved successfully.");
|
SaturnClient.LOGGER.info("Config saved successfully.");
|
||||||
} catch (IOException e) {
|
} 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 json, Map<String, Property<?>> props) {
|
||||||
private static void saveProperties(JsonObject config, Map<String, Property<?>> propertyMap) {
|
props.forEach((name, prop) -> json.add(name, prop.toJson()));
|
||||||
// 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<String, Property<?>> nestedProperties = (Map<String, Property<?>>) 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Property<?>> getProperties() {
|
public Map<String, Property<?>> getProperties() {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.lwjgl.glfw.GLFW;
|
|||||||
import org.saturnclient.saturnclient.SaturnClient;
|
import org.saturnclient.saturnclient.SaturnClient;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
|
|
||||||
public class Property<T> {
|
public class Property<T> {
|
||||||
@@ -25,7 +26,7 @@ public class Property<T> {
|
|||||||
public boolean isReset = false;
|
public boolean isReset = false;
|
||||||
private T defaultValue;
|
private T defaultValue;
|
||||||
private String[] availableValues;
|
private String[] availableValues;
|
||||||
private PropertyType type;
|
private final PropertyType type;
|
||||||
private boolean wasPressedLastTick = false;
|
private boolean wasPressedLastTick = false;
|
||||||
|
|
||||||
private Property(T value, PropertyType type) {
|
private Property(T value, PropertyType type) {
|
||||||
@@ -34,24 +35,19 @@ public class Property<T> {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------- Factory Methods ----------
|
||||||
public static <T> Property<T> from(T value) {
|
public static <T> Property<T> from(T value) {
|
||||||
if (value instanceof Boolean) {
|
if (value instanceof Boolean)
|
||||||
return new Property<>(value, PropertyType.BOOLEAN);
|
return new Property<>(value, PropertyType.BOOLEAN);
|
||||||
} else if (value instanceof Integer) {
|
if (value instanceof Integer)
|
||||||
return new Property<>(value, PropertyType.INTEGER);
|
return new Property<>(value, PropertyType.INTEGER);
|
||||||
} else if (value instanceof Float) {
|
if (value instanceof Float)
|
||||||
return new Property<>(value, PropertyType.FLOAT);
|
return new Property<>(value, PropertyType.FLOAT);
|
||||||
} else if (value instanceof String) {
|
if (value instanceof String)
|
||||||
return new Property<>(value, PropertyType.STRING);
|
return new Property<>(value, PropertyType.STRING);
|
||||||
} else if (valueIsNamespace(value)) {
|
if (valueIsNamespace(value))
|
||||||
return new Property<>(value, PropertyType.NAMESPACE);
|
return new Property<>(value, PropertyType.NAMESPACE);
|
||||||
} else {
|
return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Property<T> copy() {
|
|
||||||
return new Property<>(this.value, this.type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Property<Integer> font(int value) {
|
public static Property<Integer> font(int value) {
|
||||||
@@ -92,55 +88,37 @@ public class Property<T> {
|
|||||||
return new Property<>(value, PropertyType.KEYBINDING);
|
return new Property<>(value, PropertyType.KEYBINDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------- Select Helpers ----------
|
||||||
public void next() {
|
public void next() {
|
||||||
if ((Integer) value < availableValues.length - 1)
|
if (type == PropertyType.SELECT) {
|
||||||
setValue((Integer) value + 1);
|
int i = (Integer) value;
|
||||||
else
|
setValue((i < availableValues.length - 1) ? i + 1 : 0);
|
||||||
setValue(0);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prev() {
|
public void prev() {
|
||||||
if ((Integer) value > 0)
|
if (type == PropertyType.SELECT) {
|
||||||
setValue((Integer) value - 1);
|
int i = (Integer) value;
|
||||||
else
|
setValue((i > 0) ? i - 1 : availableValues.length - 1);
|
||||||
setValue(availableValues.length - 1);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelection(int selection) {
|
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);
|
setValue(selection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSelection() {
|
public String getSelection() {
|
||||||
if (type == PropertyType.SELECT) {
|
return (type == PropertyType.SELECT) ? availableValues[(Integer) value] : null;
|
||||||
return availableValues[(Integer) value];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------- Lifecycle ----------
|
||||||
public void reset() {
|
public void reset() {
|
||||||
value = defaultValue;
|
value = defaultValue;
|
||||||
isReset = true;
|
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() {
|
public PropertyType getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -153,34 +131,93 @@ public class Property<T> {
|
|||||||
throw new IllegalStateException("Property is not a namespace");
|
throw new IllegalStateException("Property is not a namespace");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matchesJson(JsonElement element) {
|
// ---------- JSON Serialization ----------
|
||||||
if (element.isJsonPrimitive()) {
|
/*
|
||||||
JsonPrimitive primitive = element.getAsJsonPrimitive();
|
* BOOLEAN,
|
||||||
if (value instanceof Boolean && primitive.isBoolean())
|
* INTEGER,
|
||||||
return true;
|
* FLOAT,
|
||||||
if (value instanceof Integer && primitive.isNumber())
|
* STRING,
|
||||||
return true;
|
* HEX,
|
||||||
if (value instanceof Float && primitive.isNumber())
|
* NAMESPACE,
|
||||||
return true;
|
* SELECT,
|
||||||
if (value instanceof String && primitive.isString())
|
* KEYBINDING,
|
||||||
return true;
|
*/
|
||||||
if (type == PropertyType.HEX && primitive.isString())
|
public JsonElement toJson() {
|
||||||
return true;
|
switch (type) {
|
||||||
} else if (element.isJsonObject()) {
|
case BOOLEAN:
|
||||||
return isNamespace(value);
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.valueOf(value);
|
return String.valueOf(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNamespace(Object obj) {
|
|
||||||
return type == PropertyType.NAMESPACE && value instanceof Map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean valueIsNamespace(Object obj) {
|
public static boolean valueIsNamespace(Object obj) {
|
||||||
return obj instanceof Map;
|
return obj instanceof Map;
|
||||||
}
|
}
|
||||||
@@ -200,59 +237,44 @@ public class Property<T> {
|
|||||||
return new NamedProperty<>(name, this);
|
return new NamedProperty<>(name, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------- Keybindings ----------
|
||||||
public boolean isKeyPressed() {
|
public boolean isKeyPressed() {
|
||||||
return (Integer) value == -1 ? false
|
return (Integer) value != -1 &&
|
||||||
: GLFW.glfwGetKey(SaturnClient.client.getWindow().getHandle(),
|
GLFW.glfwGetKey(SaturnClient.client.getWindow().getHandle(), (Integer) value) == GLFW.GLFW_PRESS &&
|
||||||
(Integer) (Object) value) == GLFW.GLFW_PRESS && SaturnClient.client.currentScreen == null;
|
SaturnClient.client.currentScreen == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean wasKeyPressed() {
|
public boolean wasKeyPressed() {
|
||||||
boolean isPressed = this.isKeyPressed();
|
boolean pressed = isKeyPressed();
|
||||||
wasPressedLastTick = isPressed && !wasPressedLastTick;
|
boolean result = pressed && !wasPressedLastTick;
|
||||||
return wasPressedLastTick;
|
wasPressedLastTick = pressed;
|
||||||
}
|
return result;
|
||||||
|
|
||||||
@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<Boolean>) this).setValue(value.getAsBoolean());
|
|
||||||
break;
|
|
||||||
case INTEGER:
|
|
||||||
JsonPrimitive primitive = value.getAsJsonPrimitive();
|
|
||||||
if (primitive.isNumber())
|
|
||||||
((Property<Integer>) this).setValue(value.getAsInt());
|
|
||||||
else if (primitive.isString())
|
|
||||||
((Property<Integer>) this).setValue(parseHexToInt(value.getAsString()));
|
|
||||||
break;
|
|
||||||
case FLOAT:
|
|
||||||
((Property<Float>) this).setValue(value.getAsFloat());
|
|
||||||
break;
|
|
||||||
case STRING:
|
|
||||||
((Property<String>) this).setValue(value.getAsString());
|
|
||||||
break;
|
|
||||||
case HEX:
|
|
||||||
((Property<Integer>) this).setValue(parseHexToInt(value.getAsString()));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------- HEX ----------
|
||||||
public static int parseHexToInt(String hex) {
|
public static int parseHexToInt(String hex) {
|
||||||
hex = hex.replaceAll("#", "");
|
hex = hex.replace("#", "");
|
||||||
|
if (hex.length() == 6)
|
||||||
if (hex.length() == 6) {
|
|
||||||
hex = "FF" + hex;
|
hex = "FF" + hex;
|
||||||
} else if (hex.length() != 8) {
|
if (hex.length() != 8)
|
||||||
throw new IllegalArgumentException("Hex string must be 6 or 8 characters long");
|
throw new IllegalArgumentException("Hex must be 6 or 8 chars long, got \'" + hex + "\'");
|
||||||
}
|
|
||||||
|
|
||||||
return (int) Long.parseLong(hex, 16);
|
return (int) Long.parseLong(hex, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
public Property<T> 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class HudEditor extends Screen {
|
|||||||
|
|
||||||
public HudEditor() {
|
public HudEditor() {
|
||||||
super(Text.literal("HUD Editor"));
|
super(Text.literal("HUD Editor"));
|
||||||
for (Module m : ModManager.MODS) {
|
for (Module m : ModManager.ENABLED_MODS) {
|
||||||
if (m.isEnabled() && m instanceof HudMod) {
|
if (m.isEnabled() && m instanceof HudMod) {
|
||||||
hudMods.add((HudMod) m);
|
hudMods.add((HudMod) m);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,13 +58,15 @@ public class RenderScope {
|
|||||||
int newAlpha = (opacity >>> 24) & 0xFF;
|
int newAlpha = (opacity >>> 24) & 0xFF;
|
||||||
int mixedAlpha = (originalAlpha * newAlpha) / 255;
|
int mixedAlpha = (originalAlpha * newAlpha) / 255;
|
||||||
return (mixedAlpha << 24) | (color & 0x00FFFFFF);
|
return (mixedAlpha << 24) | (color & 0x00FFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRenderLayer(Function<Identifier, RenderLayer> renderLayers) {
|
public void setRenderLayer(Function<Identifier, RenderLayer> renderLayers) {
|
||||||
// this.renderLayers = renderLayers;
|
// this.renderLayers = renderLayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawRect(int x, int y, int width, int height, int color) {
|
public void drawRect(int x, int y, int width, int height, int color) {
|
||||||
|
if (color == 0)
|
||||||
|
return;
|
||||||
color = getColor(color);
|
color = getColor(color);
|
||||||
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
|
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) {
|
public void drawText(float scale, String text, int x, int y, int font, int color) {
|
||||||
|
if (color == 0)
|
||||||
|
return;
|
||||||
if (font == 0) {
|
if (font == 0) {
|
||||||
scale *= 2;
|
scale *= 2;
|
||||||
}
|
}
|
||||||
@@ -108,7 +112,8 @@ public class RenderScope {
|
|||||||
matrices.translate(x, y + (i * Fonts.getHeight()), 0);
|
matrices.translate(x, y + (i * Fonts.getHeight()), 0);
|
||||||
matrices.scale(scale, scale, 1.0f);
|
matrices.scale(scale, scale, 1.0f);
|
||||||
TextRenderer textRenderer = SaturnClient.client.textRenderer;
|
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);
|
this.vertexConsumers, TextLayerType.NORMAL, 0, 15728880);
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
i++;
|
i++;
|
||||||
@@ -118,19 +123,19 @@ public class RenderScope {
|
|||||||
private void drawRoundedCorner(int width, int height, int radius, int color) {
|
private void drawRoundedCorner(int width, int height, int radius, int color) {
|
||||||
int w = width * 20;
|
int w = width * 20;
|
||||||
int h = height * 20;
|
int h = height * 20;
|
||||||
|
|
||||||
for (int y = 0; y < h; y++) {
|
for (int y = 0; y < h; y++) {
|
||||||
int startX = 0;
|
int startX = 0;
|
||||||
|
|
||||||
if (y < radius) {
|
if (y < radius) {
|
||||||
double dy = radius - y - 0.5;
|
double dy = radius - y - 0.5;
|
||||||
double dx = Math.sqrt(Math.max(0, radius * radius - dy * dy));
|
double dx = Math.sqrt(Math.max(0, radius * radius - dy * dy));
|
||||||
startX = radius - (int) dx;
|
startX = radius - (int) dx;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.drawRect(startX, y, w - startX, 1, color);
|
this.drawRect(startX, y, w - startX, 1, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawRoundedSide(int cornerWidth, int cornerHeight, int radius, int color) {
|
private void drawRoundedSide(int cornerWidth, int cornerHeight, int radius, int color) {
|
||||||
// Top
|
// Top
|
||||||
@@ -159,6 +164,8 @@ public class RenderScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color) {
|
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));
|
radius = Math.min(radius, Math.min(width, height));
|
||||||
int cornerWidth = width / 2;
|
int cornerWidth = width / 2;
|
||||||
int cornerHeight = height / 2;
|
int cornerHeight = height / 2;
|
||||||
@@ -183,27 +190,35 @@ public class RenderScope {
|
|||||||
public int getScaledWindowWidth() {
|
public int getScaledWindowWidth() {
|
||||||
return SaturnClient.client.getWindow().getScaledWidth();
|
return SaturnClient.client.getWindow().getScaledWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getScaledWindowHeight() {
|
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) {
|
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) {
|
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) {
|
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWith,
|
||||||
this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1);
|
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) {
|
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWidth,
|
||||||
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);
|
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;
|
x1 *= 4;
|
||||||
x2 *= 4;
|
x2 *= 4;
|
||||||
y1 *= 4;
|
y1 *= 4;
|
||||||
@@ -213,44 +228,45 @@ public class RenderScope {
|
|||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.scale(0.25f, 0.25f, 1.0f);
|
matrices.scale(0.25f, 0.25f, 1.0f);
|
||||||
RenderSystem.setShaderTexture(0, sprite);
|
RenderSystem.setShaderTexture(0, sprite);
|
||||||
RenderLayer renderLayer = (RenderLayer)RenderLayer.getGuiTextured(sprite);
|
RenderLayer renderLayer = (RenderLayer) RenderLayer.getGuiTextured(sprite);
|
||||||
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
|
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
|
||||||
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(renderLayer);
|
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) 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) 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) 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) x2, (float) y1, 0.0F).texture(u2, v1).color(color);
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableScissor(int x1, int y1, int x2, int y2) {
|
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));
|
this.setScissor(this.scissorStack.push(screenRect));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disableScissor() {
|
public void disableScissor() {
|
||||||
this.setScissor(this.scissorStack.pop());
|
this.setScissor(this.scissorStack.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean scissorContains(int x, int y) {
|
public boolean scissorContains(int x, int y) {
|
||||||
return this.scissorStack.containsPoint(x, y);
|
return this.scissorStack.containsPoint(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setScissor(@Nullable ScreenRect rect) {
|
private void setScissor(@Nullable ScreenRect rect) {
|
||||||
this.draw();
|
this.draw();
|
||||||
if (rect != null) {
|
if (rect != null) {
|
||||||
Window window = SaturnClient.client.getWindow();
|
Window window = SaturnClient.client.getWindow();
|
||||||
int i = window.getFramebufferHeight();
|
int i = window.getFramebufferHeight();
|
||||||
double d = window.getScaleFactor();
|
double d = window.getScaleFactor();
|
||||||
double e = (double)rect.getLeft() * d;
|
double e = (double) rect.getLeft() * d;
|
||||||
double f = (double)i - (double)rect.getBottom() * d;
|
double f = (double) i - (double) rect.getBottom() * d;
|
||||||
double g = (double)rect.width() * d;
|
double g = (double) rect.width() * d;
|
||||||
double h = (double)rect.height() * d;
|
double h = (double) rect.height() * d;
|
||||||
RenderSystem.enableScissor((int)e, (int)f, Math.max(0, (int)g), Math.max(0, (int)h));
|
RenderSystem.enableScissor((int) e, (int) f, Math.max(0, (int) g), Math.max(0, (int) h));
|
||||||
} else {
|
} else {
|
||||||
RenderSystem.disableScissor();
|
RenderSystem.disableScissor();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draw() {
|
public void draw() {
|
||||||
@@ -260,7 +276,7 @@ public class RenderScope {
|
|||||||
public void draw(Consumer<VertexConsumerProvider> drawer) {
|
public void draw(Consumer<VertexConsumerProvider> drawer) {
|
||||||
drawer.accept(this.vertexConsumers);
|
drawer.accept(this.vertexConsumers);
|
||||||
this.vertexConsumers.draw();
|
this.vertexConsumers.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ScissorStack {
|
static class ScissorStack {
|
||||||
private final Deque<ScreenRect> stack = new ArrayDeque<>();
|
private final Deque<ScreenRect> stack = new ArrayDeque<>();
|
||||||
@@ -268,7 +284,8 @@ public class RenderScope {
|
|||||||
public ScreenRect push(ScreenRect p_281812_) {
|
public ScreenRect push(ScreenRect p_281812_) {
|
||||||
ScreenRect screenrectangle = this.stack.peekLast();
|
ScreenRect screenrectangle = this.stack.peekLast();
|
||||||
if (screenrectangle != null) {
|
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);
|
this.stack.addLast(screenrectangle1);
|
||||||
return screenrectangle1;
|
return screenrectangle1;
|
||||||
} else {
|
} else {
|
||||||
@@ -309,47 +326,51 @@ public class RenderScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void drawItemWithoutEntity(ItemStack stack, int x, int y, int seed) {
|
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) {
|
public void drawItem(LivingEntity entity, ItemStack stack, int x, int y, int seed) {
|
||||||
this.drawItem(entity, entity.getWorld(), stack, x, y, 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);
|
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()) {
|
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.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 {
|
try {
|
||||||
this.matrices.scale(16.0F, -16.0F, 16.0F);
|
this.matrices.scale(16.0F, -16.0F, 16.0F);
|
||||||
boolean bl = !this.itemRenderState.isSideLit();
|
boolean bl = !this.itemRenderState.isSideLit();
|
||||||
if (bl) {
|
if (bl) {
|
||||||
this.draw();
|
this.draw();
|
||||||
DiffuseLighting.disableGuiDepthLighting();
|
DiffuseLighting.disableGuiDepthLighting();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.DEFAULT_UV);
|
this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.DEFAULT_UV);
|
||||||
this.draw();
|
this.draw();
|
||||||
if (bl) {
|
if (bl) {
|
||||||
DiffuseLighting.enableGuiDepthLighting();
|
DiffuseLighting.enableGuiDepthLighting();
|
||||||
}
|
}
|
||||||
} catch (Throwable var11) {
|
} catch (Throwable var11) {
|
||||||
CrashReport crashReport = CrashReport.create(var11, "Rendering item");
|
CrashReport crashReport = CrashReport.create(var11, "Rendering item");
|
||||||
CrashReportSection crashReportSection = crashReport.addElement("Item being rendered");
|
CrashReportSection crashReportSection = crashReport.addElement("Item being rendered");
|
||||||
crashReportSection.add("Item Type", () -> {
|
crashReportSection.add("Item Type", () -> {
|
||||||
return String.valueOf(stack.getItem());
|
return String.valueOf(stack.getItem());
|
||||||
});
|
});
|
||||||
crashReportSection.add("Item Components", () -> {
|
crashReportSection.add("Item Components", () -> {
|
||||||
return String.valueOf(stack.getComponents());
|
return String.valueOf(stack.getComponents());
|
||||||
});
|
});
|
||||||
crashReportSection.add("Item Foil", () -> {
|
crashReportSection.add("Item Foil", () -> {
|
||||||
return String.valueOf(stack.hasGlint());
|
return String.valueOf(stack.hasGlint());
|
||||||
});
|
});
|
||||||
throw new CrashException(crashReport);
|
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) {
|
public void drawSpriteStretched(Sprite sprite, int x, int y, int width, int height, int color) {
|
||||||
|
if (color == 0)
|
||||||
|
return;
|
||||||
if (width != 0 && height != 0) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ public class ModMenu extends SaturnScreen {
|
|||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
int col = 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));
|
scroll.draw(new SaturnModule(mod).position((160 + g) * col, (50 + g) * row));
|
||||||
|
|
||||||
if (col == 2) {
|
if (col == 2) {
|
||||||
@@ -36,7 +36,7 @@ public class ModMenu extends SaturnScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int scrollWidth = 480 + 10 + (g * 2) + (p * 2);
|
int scrollWidth = 480 + 10 + (g * 2) + (p * 2);
|
||||||
|
|
||||||
draw(scroll.dimensions(scrollWidth, 350).center(width, height));
|
draw(scroll.dimensions(scrollWidth, 350).center(width, height));
|
||||||
|
|
||||||
draw(new Sidebar(0, this::close).centerOffset(width, height, -(scrollWidth / 2 + 20), 0));
|
draw(new Sidebar(0, this::close).centerOffset(width, height, -(scrollWidth / 2 + 20), 0));
|
||||||
|
|||||||
Reference in New Issue
Block a user