From 1fe25b35be2f4e749ecb027e6b31683717ff7731 Mon Sep 17 00:00:00 2001 From: ninjaguardian <110734253+ninjaguardian@users.noreply.github.com> Date: Sun, 2 Aug 2026 15:06:22 -0500 Subject: [PATCH 1/4] Add option to store colors as hex --- .../GsonConfigSerializerBuilder.java | 10 ++++ .../impl/serializer/GsonConfigSerializer.java | 28 +++++++++-- .../impl/serializer/HexColorGsonWriter.java | 26 +++++++++++ .../v2/impl/serializer/HexColorNumber.java | 46 +++++++++++++++++++ .../yacl3/test/AutogenConfigTest.java | 1 + .../dev/isxander/yacl3/test/ConfigTest.java | 1 + 6 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorGsonWriter.java create mode 100644 src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java diff --git a/src/main/java/dev/isxander/yacl3/config/v2/api/serializer/GsonConfigSerializerBuilder.java b/src/main/java/dev/isxander/yacl3/config/v2/api/serializer/GsonConfigSerializerBuilder.java index 33003d72..75c1424b 100644 --- a/src/main/java/dev/isxander/yacl3/config/v2/api/serializer/GsonConfigSerializerBuilder.java +++ b/src/main/java/dev/isxander/yacl3/config/v2/api/serializer/GsonConfigSerializerBuilder.java @@ -94,5 +94,15 @@ static GsonConfigSerializerBuilder create(ConfigClassHandler config) { */ GsonConfigSerializerBuilder setJson5(boolean json5); + /** + * If disabled, writes colors to the json in decimal ({@code -1610612736}). + * If enabled with JSON5 ({@link #setJson5(boolean)}), writes colors to the json as hexadecimal literals ({@code 0xA0000000}). + * If enabled without JSON5, writes colors to the json as hexadecimal strings ({@code "0xA0000000"}). + * + * @param hexColor whether to store color in hexadecimal instead of decimal + * @return this builder + */ + GsonConfigSerializerBuilder setStoreColorsAsHex(boolean hexColor); + ConfigSerializer build(); } diff --git a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/GsonConfigSerializer.java b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/GsonConfigSerializer.java index 9fadd58f..b4d7ce9e 100644 --- a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/GsonConfigSerializer.java +++ b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/GsonConfigSerializer.java @@ -38,12 +38,14 @@ public class GsonConfigSerializer extends ConfigSerializer { private final Gson gson; private final Path path; private final boolean json5; + private final boolean hexColor; - private GsonConfigSerializer(ConfigClassHandler config, Path path, Gson gson, boolean json5) { + private GsonConfigSerializer(ConfigClassHandler config, Path path, Gson gson, boolean json5, boolean hexColor) { super(config); this.gson = gson; this.path = path; this.json5 = json5; + this.hexColor = hexColor; } @Override @@ -52,7 +54,7 @@ public void save() { try (StringWriter stringWriter = new StringWriter()) { JsonWriter jsonWriter = json5 ? JsonWriter.json5(stringWriter) : JsonWriter.json(stringWriter); - GsonWriter gsonWriter = new GsonWriter(jsonWriter); + GsonWriter gsonWriter = hexColor ? new HexColorGsonWriter(jsonWriter, json5) : new GsonWriter(jsonWriter); jsonWriter.beginObject(); @@ -192,12 +194,21 @@ public JsonElement serialize(Style src, Type typeOfSrc, JsonSerializationContext public static class ColorTypeAdapter implements JsonSerializer, JsonDeserializer { @Override public Color deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { - return new Color(jsonElement.getAsInt(), true); + String value = jsonElement.getAsString(); + + int argb; + if (value.startsWith("0x") || value.startsWith("0X")) + // Parse JSON5 hex literal or hex string + argb = (int) Long.parseLong(value.substring(2), 16); + else + argb = jsonElement.getAsInt(); + + return new Color(argb, true); } @Override public JsonElement serialize(Color color, Type type, JsonSerializationContext jsonSerializationContext) { - return new JsonPrimitive(color.getRGB()); + return new JsonPrimitive(new HexColorNumber(color.getRGB())); } } @@ -218,6 +229,7 @@ public static class Builder implements GsonConfigSerializerBuilder { private final ConfigClassHandler config; private Path path; private boolean json5; + private boolean hexColor; private UnaryOperator gsonBuilder = builder -> builder .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .serializeNulls() @@ -261,9 +273,15 @@ public Builder setJson5(boolean json5) { return this; } + @Override + public GsonConfigSerializerBuilder setStoreColorsAsHex(boolean hexColor) { + this.hexColor = hexColor; + return this; + } + @Override public GsonConfigSerializer build() { - return new GsonConfigSerializer<>(config, path, gsonBuilder.apply(new GsonBuilder()).create(), json5); + return new GsonConfigSerializer<>(config, path, gsonBuilder.apply(new GsonBuilder()).create(), json5, hexColor); } } } diff --git a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorGsonWriter.java b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorGsonWriter.java new file mode 100644 index 00000000..fa35ce76 --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorGsonWriter.java @@ -0,0 +1,26 @@ +package dev.isxander.yacl3.config.v2.impl.serializer; + +import org.quiltmc.parsers.json.JsonWriter; +import org.quiltmc.parsers.json.gson.GsonWriter; + +import java.io.IOException; + +public class HexColorGsonWriter extends GsonWriter { + private final boolean json5; + + public HexColorGsonWriter(JsonWriter writer, boolean json5) { + super(writer); + this.json5 = json5; + } + + @Override + public com.google.gson.stream.JsonWriter value(Number value) throws IOException { + if (!(value instanceof HexColorNumber hexColorNumber)) + return super.value(value); + + if (json5) + return jsonValue(hexColorNumber.toString()); + else + return value(hexColorNumber.toString()); + } +} diff --git a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java new file mode 100644 index 00000000..264408cd --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java @@ -0,0 +1,46 @@ +package dev.isxander.yacl3.config.v2.impl.serializer; + +public class HexColorNumber extends Number { + private final int value; + + public HexColorNumber(int value) { + this.value = value; + } + + @Override + public int intValue() { + return value; + } + + @Override + public long longValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + + @Override + public double doubleValue() { + return value; + } + + @Override + public int hashCode() { + return Integer.hashCode(value); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof HexColorNumber other)) return false; + return value == other.value; + } + + @Override + public String toString() { + return String.format("0x%08X", value); + } +} diff --git a/src/testmod/java/dev/isxander/yacl3/test/AutogenConfigTest.java b/src/testmod/java/dev/isxander/yacl3/test/AutogenConfigTest.java index b49938fb..a53c8bd4 100644 --- a/src/testmod/java/dev/isxander/yacl3/test/AutogenConfigTest.java +++ b/src/testmod/java/dev/isxander/yacl3/test/AutogenConfigTest.java @@ -28,6 +28,7 @@ public class AutogenConfigTest { .serializer(config -> GsonConfigSerializerBuilder.create(config) .setPath(YACLPlatform.getConfigDir().resolve("yacl-test-v2.json5")) .setJson5(true) + .setStoreColorsAsHex(true) .build()) .build(); diff --git a/src/testmod/java/dev/isxander/yacl3/test/ConfigTest.java b/src/testmod/java/dev/isxander/yacl3/test/ConfigTest.java index 9c5f8d6e..d06f9b27 100644 --- a/src/testmod/java/dev/isxander/yacl3/test/ConfigTest.java +++ b/src/testmod/java/dev/isxander/yacl3/test/ConfigTest.java @@ -15,6 +15,7 @@ public class ConfigTest { public static final ConfigClassHandler GSON = ConfigClassHandler.createBuilder(ConfigTest.class) .serializer(config -> GsonConfigSerializerBuilder.create(config) .setPath(YACLPlatform.getConfigDir().resolve("yacl-test.json")) + .setStoreColorsAsHex(true) .build()) .build(); From 32e3ab34494c0a0a892d514d30df37e8d867272f Mon Sep 17 00:00:00 2001 From: ninjaguardian <110734253+ninjaguardian@users.noreply.github.com> Date: Sun, 2 Aug 2026 15:29:52 -0500 Subject: [PATCH 2/4] Add clarification for hexColors --- .../config/v2/api/serializer/GsonConfigSerializerBuilder.java | 1 + src/main/java/dev/isxander/yacl3/platform/YACLConfig.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/dev/isxander/yacl3/config/v2/api/serializer/GsonConfigSerializerBuilder.java b/src/main/java/dev/isxander/yacl3/config/v2/api/serializer/GsonConfigSerializerBuilder.java index 75c1424b..953717e3 100644 --- a/src/main/java/dev/isxander/yacl3/config/v2/api/serializer/GsonConfigSerializerBuilder.java +++ b/src/main/java/dev/isxander/yacl3/config/v2/api/serializer/GsonConfigSerializerBuilder.java @@ -98,6 +98,7 @@ static GsonConfigSerializerBuilder create(ConfigClassHandler config) { * If disabled, writes colors to the json in decimal ({@code -1610612736}). * If enabled with JSON5 ({@link #setJson5(boolean)}), writes colors to the json as hexadecimal literals ({@code 0xA0000000}). * If enabled without JSON5, writes colors to the json as hexadecimal strings ({@code "0xA0000000"}). + * Colors are saved in ARGB. * * @param hexColor whether to store color in hexadecimal instead of decimal * @return this builder diff --git a/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java b/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java index 8d790042..8868ae0b 100644 --- a/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java +++ b/src/main/java/dev/isxander/yacl3/platform/YACLConfig.java @@ -10,6 +10,7 @@ public class YACLConfig { .serializer(config -> GsonConfigSerializerBuilder.create(config) .setPath(YACLPlatform.getConfigDir().resolve("yacl.json5")) .setJson5(true) + .setStoreColorsAsHex(true) .build()) .build(); From 793505e5820302686f54aab977b39fbb60ca11f5 Mon Sep 17 00:00:00 2001 From: ninjaguardian <110734253+ninjaguardian@users.noreply.github.com> Date: Sun, 2 Aug 2026 17:57:18 -0500 Subject: [PATCH 3/4] Switch to HexFormat api --- .../yacl3/config/v2/impl/serializer/HexColorNumber.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java index 264408cd..d006deb6 100644 --- a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java +++ b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java @@ -1,7 +1,10 @@ package dev.isxander.yacl3.config.v2.impl.serializer; +import java.util.HexFormat; + public class HexColorNumber extends Number { - private final int value; + private static final HexFormat HEX_FORMAT = HexFormat.of().withPrefix("0x").withUpperCase(); + protected final int value; public HexColorNumber(int value) { this.value = value; @@ -41,6 +44,6 @@ public boolean equals(Object obj) { @Override public String toString() { - return String.format("0x%08X", value); + return HEX_FORMAT.toHexDigits(value); } } From fe3297548bc77c2ebaf5792549ac20196e8cf1c3 Mon Sep 17 00:00:00 2001 From: ninjaguardian <110734253+ninjaguardian@users.noreply.github.com> Date: Sun, 2 Aug 2026 20:13:49 -0500 Subject: [PATCH 4/4] Fix hex storage --- .../impl/serializer/GsonConfigSerializer.java | 8 +++++- .../impl/serializer/HexColorGsonWriter.java | 26 ------------------- .../serializer/HexColorLiteralGsonWriter.java | 19 ++++++++++++++ .../v2/impl/serializer/HexColorNumber.java | 8 ++++-- .../serializer/HexColorStringGsonWriter.java | 19 ++++++++++++++ 5 files changed, 51 insertions(+), 29 deletions(-) delete mode 100644 src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorGsonWriter.java create mode 100644 src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorLiteralGsonWriter.java create mode 100644 src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorStringGsonWriter.java diff --git a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/GsonConfigSerializer.java b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/GsonConfigSerializer.java index b4d7ce9e..5fc548c7 100644 --- a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/GsonConfigSerializer.java +++ b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/GsonConfigSerializer.java @@ -54,7 +54,13 @@ public void save() { try (StringWriter stringWriter = new StringWriter()) { JsonWriter jsonWriter = json5 ? JsonWriter.json5(stringWriter) : JsonWriter.json(stringWriter); - GsonWriter gsonWriter = hexColor ? new HexColorGsonWriter(jsonWriter, json5) : new GsonWriter(jsonWriter); + GsonWriter gsonWriter; + if (!hexColor) + gsonWriter = new GsonWriter(jsonWriter); + else if (json5) + gsonWriter = new HexColorLiteralGsonWriter(jsonWriter); + else + gsonWriter = new HexColorStringGsonWriter(jsonWriter); jsonWriter.beginObject(); diff --git a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorGsonWriter.java b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorGsonWriter.java deleted file mode 100644 index fa35ce76..00000000 --- a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorGsonWriter.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.isxander.yacl3.config.v2.impl.serializer; - -import org.quiltmc.parsers.json.JsonWriter; -import org.quiltmc.parsers.json.gson.GsonWriter; - -import java.io.IOException; - -public class HexColorGsonWriter extends GsonWriter { - private final boolean json5; - - public HexColorGsonWriter(JsonWriter writer, boolean json5) { - super(writer); - this.json5 = json5; - } - - @Override - public com.google.gson.stream.JsonWriter value(Number value) throws IOException { - if (!(value instanceof HexColorNumber hexColorNumber)) - return super.value(value); - - if (json5) - return jsonValue(hexColorNumber.toString()); - else - return value(hexColorNumber.toString()); - } -} diff --git a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorLiteralGsonWriter.java b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorLiteralGsonWriter.java new file mode 100644 index 00000000..f974f65a --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorLiteralGsonWriter.java @@ -0,0 +1,19 @@ +package dev.isxander.yacl3.config.v2.impl.serializer; + +import org.quiltmc.parsers.json.JsonWriter; +import org.quiltmc.parsers.json.gson.GsonWriter; + +import java.io.IOException; + +public class HexColorLiteralGsonWriter extends GsonWriter { + public HexColorLiteralGsonWriter(JsonWriter writer) { + super(writer); + } + + @Override + public com.google.gson.stream.JsonWriter value(Number value) throws IOException { + return value instanceof HexColorNumber hexColorNumber + ? jsonValue(hexColorNumber.hex()) + : super.value(value); + } +} diff --git a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java index d006deb6..f306a47c 100644 --- a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java +++ b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java @@ -3,13 +3,17 @@ import java.util.HexFormat; public class HexColorNumber extends Number { - private static final HexFormat HEX_FORMAT = HexFormat.of().withPrefix("0x").withUpperCase(); + private static final HexFormat HEX_FORMAT = HexFormat.of().withUpperCase(); protected final int value; public HexColorNumber(int value) { this.value = value; } + public String hex() { + return "0x" + HEX_FORMAT.toHexDigits(value); + } + @Override public int intValue() { return value; @@ -44,6 +48,6 @@ public boolean equals(Object obj) { @Override public String toString() { - return HEX_FORMAT.toHexDigits(value); + return String.valueOf(value); } } diff --git a/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorStringGsonWriter.java b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorStringGsonWriter.java new file mode 100644 index 00000000..cf4ff1e3 --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorStringGsonWriter.java @@ -0,0 +1,19 @@ +package dev.isxander.yacl3.config.v2.impl.serializer; + +import org.quiltmc.parsers.json.JsonWriter; +import org.quiltmc.parsers.json.gson.GsonWriter; + +import java.io.IOException; + +public class HexColorStringGsonWriter extends GsonWriter { + public HexColorStringGsonWriter(JsonWriter writer) { + super(writer); + } + + @Override + public com.google.gson.stream.JsonWriter value(Number value) throws IOException { + return value instanceof HexColorNumber hexColorNumber + ? value(hexColorNumber.hex()) + : super.value(value); + } +}