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..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 @@ -94,5 +94,16 @@ 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"}). + * Colors are saved in ARGB. + * + * @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..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 @@ -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,13 @@ public void save() { try (StringWriter stringWriter = new StringWriter()) { JsonWriter jsonWriter = json5 ? JsonWriter.json5(stringWriter) : JsonWriter.json(stringWriter); - GsonWriter gsonWriter = 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(); @@ -192,12 +200,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 +235,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 +279,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/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 new file mode 100644 index 00000000..f306a47c --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/config/v2/impl/serializer/HexColorNumber.java @@ -0,0 +1,53 @@ +package dev.isxander.yacl3.config.v2.impl.serializer; + +import java.util.HexFormat; + +public class HexColorNumber extends Number { + 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; + } + + @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.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); + } +} 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(); 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();