Config manager and property
This commit is contained in:
@@ -4,4 +4,6 @@ public abstract class MinecraftProvider {
|
|||||||
public static MinecraftProvider PROVIDER;
|
public static MinecraftProvider PROVIDER;
|
||||||
|
|
||||||
public abstract Object createIdentifier(String namespace, String path);
|
public abstract Object createIdentifier(String namespace, String path);
|
||||||
|
|
||||||
|
public abstract boolean isKeyPressed(int key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package org.saturnclient.config;
|
||||||
|
|
||||||
|
import org.saturnclient.saturnclient.config.manager.ConfigManager;
|
||||||
|
import org.saturnclient.saturnclient.config.manager.Property;
|
||||||
|
|
||||||
|
public class AnimationConfig {
|
||||||
|
public static ConfigManager config;
|
||||||
|
|
||||||
|
// Logo
|
||||||
|
public static final AnimationConfig logo = new AnimationConfig(true, 700, 0);
|
||||||
|
|
||||||
|
// Main menu
|
||||||
|
public static final AnimationConfig mainMenu = new AnimationConfig(true, 700, 120);
|
||||||
|
|
||||||
|
// Mod menu
|
||||||
|
public static final AnimationConfig modMenu = new AnimationConfig(true, 700, 20);
|
||||||
|
|
||||||
|
// Shift menu
|
||||||
|
public static final AnimationConfig shiftMenu = new AnimationConfig(true, 700, 100);
|
||||||
|
|
||||||
|
// Cosmetics menu
|
||||||
|
public static final AnimationConfig cosmeticsMenu = new AnimationConfig(true, 700, 40);
|
||||||
|
|
||||||
|
// Emote wheel
|
||||||
|
public static final AnimationConfig emoteWheel = new AnimationConfig(true, 700, 40);
|
||||||
|
|
||||||
|
public static void init(ConfigManager parent) {
|
||||||
|
config = new ConfigManager(parent, "Animations");
|
||||||
|
|
||||||
|
logo.init("Logo");
|
||||||
|
mainMenu.init("Main Menu");
|
||||||
|
modMenu.init("Mod Menu");
|
||||||
|
shiftMenu.init("Shift Menu");
|
||||||
|
cosmeticsMenu.init("Cosmetics Menu");
|
||||||
|
emoteWheel.init("Emote Wheel");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animation properties
|
||||||
|
public final Property<Integer> duration;
|
||||||
|
public final Property<Integer> stagger;
|
||||||
|
public final Property<Integer> curve;
|
||||||
|
|
||||||
|
public AnimationConfig(boolean enabled, int delay, int stagger) {
|
||||||
|
this.duration = Property.integer(delay);
|
||||||
|
this.stagger = Property.integer(stagger);
|
||||||
|
this.curve = Property.select(1, "Ease In Out Cubic", "Ease Out Cubic", "Ease In Out Back");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(String name) {
|
||||||
|
// config.property("Enable " + name + " Animations", this.enabled);
|
||||||
|
config.property(name + " Duration", this.duration);
|
||||||
|
config.property(name + " Stagger", this.stagger);
|
||||||
|
config.property(name + " Curve", this.curve);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package org.saturnclient.saturnclient.config;
|
||||||
|
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.saturnclient.saturnclient.config.manager.ConfigManager;
|
||||||
|
import org.saturnclient.saturnclient.config.manager.Property;
|
||||||
|
import org.saturnclient.ui.resources.Textures;
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class Config {
|
||||||
|
public static ConfigManager config;
|
||||||
|
|
||||||
|
public static Property<Boolean> realisticLogo = Property.bool(false);
|
||||||
|
public static Property<Boolean> saturnTitleScreen = Property.bool(true);
|
||||||
|
public static Property<Boolean> cloakPhysics = Property.bool(true);
|
||||||
|
public static Property<Integer> openEmoteWheel = Property.keybinding(GLFW.GLFW_KEY_B);
|
||||||
|
public static Property<Boolean> stagger = Property.bool(true);
|
||||||
|
|
||||||
|
public static Identifier getLogo() {
|
||||||
|
return realisticLogo.value ? Textures.REALISTIC_LOGO : Textures.LOGO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
config = new ConfigManager("Saturn Client");
|
||||||
|
config.property("Realistic logo", realisticLogo);
|
||||||
|
config.property("Saturn client title screen", saturnTitleScreen);
|
||||||
|
config.property("Open Emote Wheel", openEmoteWheel);
|
||||||
|
config.property("Cloak Physics", cloakPhysics);
|
||||||
|
config.property("Stagger Animations", stagger);
|
||||||
|
|
||||||
|
// Initialize a sub namespace for theme
|
||||||
|
Theme.init(config);
|
||||||
|
|
||||||
|
// Initialize a sub namespace for animations
|
||||||
|
AnimationConfig.init(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package org.saturnclient.saturnclient.config;
|
||||||
|
|
||||||
|
import org.saturnclient.saturnclient.config.manager.ConfigManager;
|
||||||
|
import org.saturnclient.saturnclient.config.manager.Property;
|
||||||
|
|
||||||
|
public class Theme {
|
||||||
|
// Main UI background (slightly warm dark to match Saturn tone)
|
||||||
|
public static final Property<Integer> BACKGROUND = Property.color(0xFF12100D);
|
||||||
|
|
||||||
|
// Default text color
|
||||||
|
public static final Property<Integer> FOREGROUND = Property.color(0xFFF2E6D2);
|
||||||
|
|
||||||
|
// Widget default background (normal state)
|
||||||
|
public static final Property<Integer> PRIMARY = Property.color(0xFF1C1915);
|
||||||
|
|
||||||
|
// Widget text color
|
||||||
|
public static final Property<Integer> PRIMARY_FG = Property.color(0xFFEAD9B8);
|
||||||
|
|
||||||
|
// Saturn brand color (hovered / enabled / selected)
|
||||||
|
public static final Property<Integer> ACCENT = Property.color(0xFFE2BF7D);
|
||||||
|
|
||||||
|
// Text/icons shown on accent background
|
||||||
|
public static final Property<Integer> ACCENT_FG = Property.color(0xFF1A140A);
|
||||||
|
|
||||||
|
// Misc colors
|
||||||
|
public static final Property<Integer> SCROLL = Property.color(0xFFE2BF7D);
|
||||||
|
|
||||||
|
// UI metrics
|
||||||
|
public static final Property<Integer> BG_RADIUS = Property.integer(12);
|
||||||
|
public static final Property<Integer> WIDGET_RADIUS = Property.integer(10);
|
||||||
|
|
||||||
|
// Font
|
||||||
|
public static final Property<Integer> FONT = Property.font(2);
|
||||||
|
|
||||||
|
public static void init(ConfigManager parent) {
|
||||||
|
ConfigManager config = new ConfigManager(parent, "UI Style");
|
||||||
|
config.property("Background", BACKGROUND);
|
||||||
|
config.property("Foreground", FOREGROUND);
|
||||||
|
config.property("Primary", PRIMARY);
|
||||||
|
config.property("Primary Foreground", PRIMARY_FG);
|
||||||
|
config.property("Accent", ACCENT);
|
||||||
|
config.property("Accent Foreground", ACCENT_FG);
|
||||||
|
config.property("Scrollbar Color", SCROLL);
|
||||||
|
|
||||||
|
config.property("Background Radius", BG_RADIUS);
|
||||||
|
config.property("Widget Radius", WIDGET_RADIUS);
|
||||||
|
|
||||||
|
config.property("Font", FONT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* primary by default, accent if true
|
||||||
|
*/
|
||||||
|
public static int getBg(boolean hover) {
|
||||||
|
return hover ? ACCENT.value : PRIMARY.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Foreground) primary by default, accent if true
|
||||||
|
*/
|
||||||
|
public static int getFg(boolean hover) {
|
||||||
|
return hover ? ACCENT_FG.value : PRIMARY_FG.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplies existing alpha with 0–255 alpha.
|
||||||
|
*/
|
||||||
|
public static int withAlpha(int alpha, int color) {
|
||||||
|
alpha = Math.max(0, Math.min(255, alpha));
|
||||||
|
|
||||||
|
int originalAlpha = (color >>> 24) & 0xFF;
|
||||||
|
|
||||||
|
// Merge (multiply) alphas
|
||||||
|
int merged = (originalAlpha * alpha) / 255;
|
||||||
|
|
||||||
|
return (color & 0x00FFFFFF) | (merged << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplies existing alpha with 0.0–1.0 alpha.
|
||||||
|
*/
|
||||||
|
public static int withAlpha(float alpha, int color) {
|
||||||
|
alpha = Math.max(0f, Math.min(1f, alpha));
|
||||||
|
|
||||||
|
int originalAlpha = (color >>> 24) & 0xFF;
|
||||||
|
|
||||||
|
int merged = (int) (originalAlpha * alpha);
|
||||||
|
|
||||||
|
return (color & 0x00FFFFFF) | (merged << 24);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
package org.saturnclient.config.manager;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ConfigManager {
|
||||||
|
|
||||||
|
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
|
// SINGLE ROOT TREE
|
||||||
|
private static final Map<String, Property<?>> ROOT = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
private static JsonNode cachedJson = null;
|
||||||
|
|
||||||
|
private final Map<String, Property<?>> currentMap;
|
||||||
|
|
||||||
|
private final String[] path;
|
||||||
|
|
||||||
|
private File configFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a root namespace
|
||||||
|
*/
|
||||||
|
public ConfigManager(File configFile, String namespace) {
|
||||||
|
this.configFile = configFile;
|
||||||
|
this.currentMap = new LinkedHashMap<>();
|
||||||
|
this.path = new String[] { namespace };
|
||||||
|
|
||||||
|
ROOT.put(namespace, Property.namespace(currentMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a sub-namespace inside a parent
|
||||||
|
*/
|
||||||
|
public ConfigManager(ConfigManager parent, String namespace) {
|
||||||
|
this.configFile = parent.configFile;
|
||||||
|
this.currentMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
this.path = new String[parent.path.length + 1];
|
||||||
|
System.arraycopy(parent.path, 0, this.path, 0, parent.path.length);
|
||||||
|
this.path[this.path.length - 1] = namespace;
|
||||||
|
|
||||||
|
parent.property(namespace, Property.namespace(currentMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a property
|
||||||
|
*/
|
||||||
|
public <T> Property<T> property(String name, Property<T> value) {
|
||||||
|
currentMap.put(name, value);
|
||||||
|
loadSingleProperty(name, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add empty namespace
|
||||||
|
*/
|
||||||
|
public ConfigManager sub(String name) {
|
||||||
|
return new ConfigManager(this, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load entire config
|
||||||
|
*/
|
||||||
|
public void load() {
|
||||||
|
JsonNode json = loadAndCache();
|
||||||
|
if (json == null || !json.isObject())
|
||||||
|
return;
|
||||||
|
|
||||||
|
loadRecursive((ObjectNode) json, ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save entire config
|
||||||
|
*/
|
||||||
|
public void save() {
|
||||||
|
|
||||||
|
ObjectNode rootJson = MAPPER.createObjectNode();
|
||||||
|
saveRecursive(rootJson, ROOT);
|
||||||
|
|
||||||
|
try {
|
||||||
|
MAPPER.writerWithDefaultPrettyPrinter().writeValue(configFile, rootJson);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursive save
|
||||||
|
*/
|
||||||
|
private static void saveRecursive(ObjectNode json, Map<String, Property<?>> map) {
|
||||||
|
map.forEach((name, prop) -> {
|
||||||
|
if (prop.isNamespace()) {
|
||||||
|
|
||||||
|
ObjectNode child = json.objectNode();
|
||||||
|
saveRecursive(child, prop.getNamespaceMap());
|
||||||
|
|
||||||
|
json.set(name, child);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
json.set(name, prop.toJson());
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursive load
|
||||||
|
*/
|
||||||
|
private static void loadRecursive(ObjectNode json, Map<String, Property<?>> map) {
|
||||||
|
|
||||||
|
map.forEach((name, prop) -> {
|
||||||
|
|
||||||
|
JsonNode element = json.get(name);
|
||||||
|
if (element == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (prop.isNamespace() && element.isObject()) {
|
||||||
|
|
||||||
|
loadRecursive((ObjectNode) element, prop.getNamespaceMap());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
prop.loadFromJson(element);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load only a single property immediately after creation
|
||||||
|
*/
|
||||||
|
private void loadSingleProperty(String name, Property<?> prop) {
|
||||||
|
|
||||||
|
JsonNode source = cachedJson != null ? cachedJson : loadAndCache();
|
||||||
|
if (source == null || !source.isObject())
|
||||||
|
return;
|
||||||
|
|
||||||
|
JsonNode currentScope = source;
|
||||||
|
|
||||||
|
for (String segment : path) {
|
||||||
|
|
||||||
|
JsonNode next = currentScope.get(segment);
|
||||||
|
|
||||||
|
if (next != null && next.isObject()) {
|
||||||
|
currentScope = next;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode element = currentScope.get(name);
|
||||||
|
|
||||||
|
if (element != null) {
|
||||||
|
prop.loadFromJson(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads file and caches json
|
||||||
|
*/
|
||||||
|
private JsonNode loadAndCache() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (!configFile.exists()) {
|
||||||
|
|
||||||
|
Files.writeString(configFile.toPath(), "{}");
|
||||||
|
cachedJson = MAPPER.createObjectNode();
|
||||||
|
return cachedJson;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedJson = MAPPER.readTree(configFile);
|
||||||
|
return cachedJson;
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Property<?>> getProperties() {
|
||||||
|
return currentMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,321 @@
|
|||||||
|
package org.saturnclient.config.manager;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Property<T> {
|
||||||
|
|
||||||
|
public static class NamedProperty<T> {
|
||||||
|
public String name;
|
||||||
|
public Property<T> prop;
|
||||||
|
|
||||||
|
public NamedProperty(String name, Property<T> value) {
|
||||||
|
this.name = name;
|
||||||
|
this.prop = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PropertyType {
|
||||||
|
BOOLEAN,
|
||||||
|
INTEGER,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
HEX,
|
||||||
|
NAMESPACE,
|
||||||
|
SELECT,
|
||||||
|
KEYBINDING,
|
||||||
|
}
|
||||||
|
|
||||||
|
public T value;
|
||||||
|
public boolean isReset = false;
|
||||||
|
private T defaultValue;
|
||||||
|
private String[] availableValues;
|
||||||
|
private final PropertyType type;
|
||||||
|
private boolean wasPressedLastTick = false;
|
||||||
|
|
||||||
|
private Property(T value, PropertyType type) {
|
||||||
|
this.value = value;
|
||||||
|
this.defaultValue = value;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Factory Methods ----------
|
||||||
|
|
||||||
|
public static <T> Property<T> from(T value) {
|
||||||
|
if (value instanceof Boolean)
|
||||||
|
return new Property<>(value, PropertyType.BOOLEAN);
|
||||||
|
if (value instanceof Integer)
|
||||||
|
return new Property<>(value, PropertyType.INTEGER);
|
||||||
|
if (value instanceof Float)
|
||||||
|
return new Property<>(value, PropertyType.FLOAT);
|
||||||
|
if (value instanceof String)
|
||||||
|
return new Property<>(value, PropertyType.STRING);
|
||||||
|
if (valueIsNamespace(value))
|
||||||
|
return new Property<>(value, PropertyType.NAMESPACE);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Property<Integer> font(int value) {
|
||||||
|
return select(value, "Default", "Inter", "Inter bold");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Property<Integer> select(Integer value, String... availableValues) {
|
||||||
|
Property<Integer> property = new Property<>(value, PropertyType.SELECT);
|
||||||
|
property.availableValues = availableValues;
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Property<Map<String, Property<?>>> namespace(Map<String, Property<?>> value) {
|
||||||
|
return new Property<>(value, PropertyType.NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Property<Boolean> bool(boolean value) {
|
||||||
|
return new Property<>(value, PropertyType.BOOLEAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Property<Integer> integer(int value) {
|
||||||
|
return new Property<>(value, PropertyType.INTEGER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Property<Float> floatProp(float value) {
|
||||||
|
return new Property<>(value, PropertyType.FLOAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Property<String> string(String value) {
|
||||||
|
return new Property<>(value, PropertyType.STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Property<Integer> color(int value) {
|
||||||
|
return new Property<>(value, PropertyType.HEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Property<Integer> keybinding(int value) {
|
||||||
|
return new Property<>(value, PropertyType.KEYBINDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Select Helpers ----------
|
||||||
|
|
||||||
|
public void next() {
|
||||||
|
if (type == PropertyType.SELECT) {
|
||||||
|
int i = (Integer) value;
|
||||||
|
setValue((i < availableValues.length - 1) ? i + 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prev() {
|
||||||
|
if (type == PropertyType.SELECT) {
|
||||||
|
int i = (Integer) value;
|
||||||
|
setValue((i > 0) ? i - 1 : availableValues.length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelection(int selection) {
|
||||||
|
if (type == PropertyType.SELECT && selection >= 0 && selection < availableValues.length) {
|
||||||
|
setValue(selection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSelection() {
|
||||||
|
return (type == PropertyType.SELECT) ? availableValues[(Integer) value] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Lifecycle ----------
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
value = defaultValue;
|
||||||
|
isReset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Map<String, Property<?>> getNamespaceValue() {
|
||||||
|
if (type == PropertyType.NAMESPACE && value instanceof Map) {
|
||||||
|
return (Map<String, Property<?>>) value;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Property is not a namespace");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- JSON Serialization ----------
|
||||||
|
|
||||||
|
public JsonNode toJson() {
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case BOOLEAN:
|
||||||
|
return JsonNodeFactory.instance.booleanNode((Boolean) value);
|
||||||
|
|
||||||
|
case INTEGER:
|
||||||
|
return JsonNodeFactory.instance.numberNode((Integer) value);
|
||||||
|
|
||||||
|
case FLOAT:
|
||||||
|
return JsonNodeFactory.instance.numberNode((Float) value);
|
||||||
|
|
||||||
|
case STRING:
|
||||||
|
return JsonNodeFactory.instance.textNode((String) value);
|
||||||
|
|
||||||
|
case HEX:
|
||||||
|
return JsonNodeFactory.instance.textNode(
|
||||||
|
String.format("#%08X", (Integer) value));
|
||||||
|
|
||||||
|
case KEYBINDING:
|
||||||
|
case SELECT:
|
||||||
|
return JsonNodeFactory.instance.numberNode((Integer) value);
|
||||||
|
|
||||||
|
case NAMESPACE:
|
||||||
|
|
||||||
|
ObjectNode nested = JsonNodeFactory.instance.objectNode();
|
||||||
|
|
||||||
|
getNamespaceValue().forEach((k, v) -> {
|
||||||
|
nested.set(k, v.toJson());
|
||||||
|
});
|
||||||
|
|
||||||
|
return nested;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return JsonNodeFactory.instance.textNode(String.valueOf(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadFromJson(JsonNode element) {
|
||||||
|
|
||||||
|
if (element == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case BOOLEAN:
|
||||||
|
if (element.isBoolean())
|
||||||
|
setValue(element.booleanValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INTEGER:
|
||||||
|
if (element.isInt())
|
||||||
|
setValue(element.intValue());
|
||||||
|
else if (element.isTextual())
|
||||||
|
setValue(parseHexToInt(element.textValue()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FLOAT:
|
||||||
|
if (element.isNumber())
|
||||||
|
setValue(element.floatValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STRING:
|
||||||
|
if (element.isTextual())
|
||||||
|
setValue(element.textValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HEX:
|
||||||
|
if (element.isTextual())
|
||||||
|
setValue(parseHexToInt(element.textValue()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAMESPACE:
|
||||||
|
|
||||||
|
if (element.isObject()) {
|
||||||
|
|
||||||
|
ObjectNode obj = (ObjectNode) element;
|
||||||
|
|
||||||
|
getNamespaceValue().forEach((k, v) -> {
|
||||||
|
v.loadFromJson(obj.get(k));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SELECT:
|
||||||
|
if (element.isInt())
|
||||||
|
setSelection(element.intValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEYBINDING:
|
||||||
|
if (element.isInt())
|
||||||
|
setValue(element.intValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Utility ----------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean valueIsNamespace(Object obj) {
|
||||||
|
return obj instanceof Map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void setValue(Object value) {
|
||||||
|
this.value = (T) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void setValue(Object value, Object defaultValue) {
|
||||||
|
this.value = (T) value;
|
||||||
|
this.defaultValue = (T) defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NamedProperty<T> named(String name) {
|
||||||
|
return new NamedProperty<>(name, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Keybindings (no SaturnClient) ----------
|
||||||
|
|
||||||
|
public boolean isKeyPressed(long windowHandle, boolean screenOpen) {
|
||||||
|
|
||||||
|
return (Integer) value != -1 &&
|
||||||
|
MinecraftProvider.PROVIDER.isKeyPressed((Integer) value) && !screenOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wasKeyPressed(long windowHandle, boolean screenOpen) {
|
||||||
|
|
||||||
|
boolean pressed = isKeyPressed(windowHandle, screenOpen);
|
||||||
|
|
||||||
|
boolean result = pressed && !wasPressedLastTick;
|
||||||
|
|
||||||
|
wasPressedLastTick = pressed;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- HEX ----------
|
||||||
|
|
||||||
|
public static int parseHexToInt(String hex) {
|
||||||
|
|
||||||
|
hex = hex.replace("#", "");
|
||||||
|
|
||||||
|
if (hex.length() == 6)
|
||||||
|
hex = "FF" + hex;
|
||||||
|
|
||||||
|
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<T> copy() {
|
||||||
|
return new Property<>(this.value, this.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNamespace() {
|
||||||
|
return type == PropertyType.NAMESPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Map<String, Property<?>> getNamespaceMap() {
|
||||||
|
return isNamespace() ? (Map<String, Property<?>>) value : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user