Skip to content

Commit 0f8d94b

Browse files
committed
Rewrite color manager in Java
The rewrite is more crash-proof and uses JSON instead of JSON5.
1 parent 2d1811c commit 0f8d94b

File tree

8 files changed

+145
-120
lines changed

8 files changed

+145
-120
lines changed

common/src/main/java/juuxel/adorn/client/gui/screen/PalettedMenuScreen.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ private ColorManager.ColorPair getPalette() {
3030

3131
@Override
3232
protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {
33-
var bg = getPalette().getBg();
33+
var bg = getPalette().bg();
3434
RenderSystem.setShaderColor(Colors.redOf(bg), Colors.greenOf(bg), Colors.blueOf(bg), 1.0f);
3535
context.drawTexture(getBackgroundTexture(), x, y, 0, 0, backgroundWidth, backgroundHeight);
3636
RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
3737
}
3838

3939
@Override
4040
protected void drawForeground(DrawContext context, int mouseX, int mouseY) {
41-
var fg = getPalette().getFg();
41+
var fg = getPalette().fg();
4242
context.drawText(textRenderer, title, titleX, titleY, fg, false);
4343
context.drawText(textRenderer, playerInventoryTitle, playerInventoryTitleX, playerInventoryTitleY, fg, false);
4444
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package juuxel.adorn.client.resources;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.JsonObject;
5+
import com.google.gson.JsonParseException;
6+
import com.mojang.serialization.Codec;
7+
import com.mojang.serialization.DataResult;
8+
import com.mojang.serialization.JsonOps;
9+
import com.mojang.serialization.codecs.RecordCodecBuilder;
10+
import juuxel.adorn.AdornCommon;
11+
import juuxel.adorn.util.Colors;
12+
import juuxel.adorn.util.ColorsKt;
13+
import juuxel.adorn.util.Logging;
14+
import net.minecraft.resource.ResourceFinder;
15+
import net.minecraft.resource.ResourceManager;
16+
import net.minecraft.resource.SinglePreparationResourceReloader;
17+
import net.minecraft.util.Identifier;
18+
import net.minecraft.util.dynamic.Codecs;
19+
import net.minecraft.util.profiler.Profiler;
20+
import org.slf4j.Logger;
21+
22+
import java.io.IOException;
23+
import java.util.ArrayList;
24+
import java.util.HashMap;
25+
import java.util.HexFormat;
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.function.Function;
29+
import java.util.regex.Pattern;
30+
31+
public class ColorManager extends SinglePreparationResourceReloader<Map<Identifier, List<JsonObject>>> {
32+
private static final Logger LOGGER = Logging.logger();
33+
private static final Identifier FALLBACK = AdornCommon.id("fallback");
34+
private static final String PREFIX = "adorn/color_palettes";
35+
private static final Pattern COLOR_REGEX = Pattern.compile("^#(?:[0-9A-Fa-f]{2})?[0-9A-Fa-f]{6}$");
36+
private static final Codec<Map<Identifier, ColorPair>> PALETTE_CODEC = Codec.unboundedMap(Identifier.CODEC, ColorPair.CODEC);
37+
38+
private final Map<Identifier, ColorPalette> palettes = new HashMap<>();
39+
40+
@Override
41+
protected Map<Identifier, List<JsonObject>> prepare(ResourceManager manager, Profiler profiler) {
42+
var gson = new Gson();
43+
var resourceFinder = ResourceFinder.json(PREFIX);
44+
Map<Identifier, List<JsonObject>> result = new HashMap<>();
45+
46+
for (var entry : resourceFinder.findAllResources(manager).entrySet()) {
47+
var id = resourceFinder.toResourceId(entry.getKey());
48+
List<JsonObject> jsons = new ArrayList<>();
49+
result.put(id, jsons);
50+
51+
for (var resource : entry.getValue()) {
52+
try (var in = resource.getReader()) {
53+
jsons.add(gson.fromJson(in, JsonObject.class));
54+
} catch (IOException | JsonParseException e) {
55+
LOGGER.error("[Adorn] Could not load color palette resource {} from {}", entry.getKey(), resource.getResourcePackName(), e);
56+
}
57+
}
58+
}
59+
60+
return result;
61+
}
62+
63+
@Override
64+
protected void apply(Map<Identifier, List<JsonObject>> prepared, ResourceManager manager, Profiler profiler) {
65+
palettes.clear();
66+
prepared.forEach((id, jsons) -> {
67+
var palette = new HashMap<Identifier, ColorPair>();
68+
69+
for (var json : jsons) {
70+
var partialPalette = PALETTE_CODEC.parse(JsonOps.INSTANCE, json).get()
71+
.map(Function.identity(), partial -> {
72+
LOGGER.error("[Adorn] Could not parse color palette {}", id);
73+
return null;
74+
});
75+
if (partialPalette == null) continue;
76+
palette.putAll(partialPalette);
77+
}
78+
79+
palettes.put(id, new ColorPalette(palette));
80+
});
81+
}
82+
83+
public ColorPalette getColors(Identifier id) {
84+
var pair = palettes.get(id);
85+
if (pair == null) {
86+
pair = palettes.get(FALLBACK);
87+
if (pair == null) {
88+
throw new IllegalStateException("Could not find fallback palette!");
89+
}
90+
}
91+
return pair;
92+
}
93+
94+
private static DataResult<Integer> parseHexColor(String str) {
95+
if (!COLOR_REGEX.matcher(str).matches()) {
96+
return DataResult.error(() -> "Color must be a hex color beginning with '#' - found " + str);
97+
}
98+
99+
var colorStr = str.substring(1);
100+
return DataResult.success(switch (colorStr.length()) {
101+
case 6 -> ColorsKt.color(Integer.parseInt(colorStr, 16));
102+
case 8 -> Integer.parseInt(colorStr, 16);
103+
default -> throw new MatchException("Mismatching color length: " + colorStr.length(), null);
104+
});
105+
}
106+
107+
public record ColorPair(int bg, int fg) {
108+
private static final int DEFAULT_FG = Colors.SCREEN_TEXT;
109+
110+
public static final Codec<ColorPair> CODEC = Codecs.alternatively(
111+
RecordCodecBuilder.create(instance -> instance.group(
112+
Codec.INT.fieldOf("bg").forGetter(ColorPair::bg),
113+
Codec.INT.optionalFieldOf("fg", DEFAULT_FG).forGetter(ColorPair::bg)
114+
).apply(instance, ColorPair::new)),
115+
Codec.STRING.comapFlatMap(ColorManager::parseHexColor, color -> HexFormat.of().withUpperCase().toHexDigits(color))
116+
.xmap(bg -> new ColorPair(bg, DEFAULT_FG), ColorPair::bg)
117+
);
118+
}
119+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package juuxel.adorn.client.resources;
2+
3+
import juuxel.adorn.AdornCommon;
4+
import net.minecraft.util.Identifier;
5+
6+
import java.util.Map;
7+
8+
public final class ColorPalette {
9+
private static final Identifier DEFAULT_COLOR_ID = AdornCommon.id("default");
10+
private final Map<Identifier, ColorManager.ColorPair> map;
11+
12+
public ColorPalette(Map<Identifier, ColorManager.ColorPair> map) {
13+
this.map = Map.copyOf(map);
14+
}
15+
16+
public ColorManager.ColorPair get(Identifier key) {
17+
var pair = map.get(key);
18+
if (pair == null) {
19+
pair = map.get(DEFAULT_COLOR_ID);
20+
if (pair == null) throw new IllegalStateException("Couldn't read default value from palette map");
21+
}
22+
return pair;
23+
}
24+
}

common/src/main/kotlin/juuxel/adorn/client/resources/ColorManager.kt

-98
This file was deleted.

common/src/main/kotlin/juuxel/adorn/client/resources/ColorPalette.kt

-18
This file was deleted.

common/src/main/resources/assets/adorn/adorn/color_palettes/drawer.json5 common/src/main/resources/assets/adorn/adorn/color_palettes/drawer.json

-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,5 @@
2222

2323
"adorn:traverse/fir_drawer": { "bg": "#8E5E3D" },
2424

25-
// The default color is the oak color
2625
"adorn:default": "#BE9A60"
2726
}

common/src/main/resources/assets/adorn/adorn/color_palettes/kitchen_cupboard.json5 common/src/main/resources/assets/adorn/adorn/color_palettes/kitchen_cupboard.json

-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,5 @@
2222

2323
"adorn:traverse/fir_kitchen_cupboard": { "bg": "#8E5E3D" },
2424

25-
// The default color is the oak color
2625
"adorn:default": "#BE9A60"
2726
}

0 commit comments

Comments
 (0)