package io.gitlab.jfronny.resclone; import com.google.gson.reflect.TypeToken; import io.gitlab.jfronny.commons.serialize.gson.api.v1.GsonHolders; import io.gitlab.jfronny.gson.JsonParseException; import io.gitlab.jfronny.gson.stream.*; import io.gitlab.jfronny.libjf.config.api.v1.JfCustomConfig; import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL; import io.gitlab.jfronny.resclone.data.PackMetaUnloaded; import java.io.*; import java.lang.reflect.Type; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashSet; import java.util.Set; public class RescloneConfig implements JfCustomConfig { public static Set packs; public static boolean pruneUnused; private static final String PACKS = "packs"; private static final String PRUNE_UNUSED = "pruneUnused"; private static final Type META_SET = new TypeToken>(){}.getType(); private static void load(Path path) throws IOException { if (!Files.exists(path)) { packs = new HashSet<>(); pruneUnused = true; write(path); return; } boolean updateRequired = false; try (BufferedReader br = Files.newBufferedReader(path); JsonReader reader = GsonHolders.CONFIG.getGson().newJsonReader(br)) { if (reader.peek() == JsonToken.BEGIN_ARRAY) { // Legacy format compatibility packs = GsonHolders.CONFIG.getGson().fromJson(reader, META_SET); updateRequired = true; } else if (reader.peek() == JsonToken.BEGIN_OBJECT) { // New format reader.beginObject(); Set packs = null; Boolean pruneUnused = null; while (reader.peek() != JsonToken.END_OBJECT) { final String name = reader.nextName(); switch (name) { case PACKS -> { if (packs != null) throw new JsonParseException("Unexpected duplicate \"" + PACKS + "\" in Resclone config"); packs = GsonHolders.CONFIG.getGson().fromJson(reader, META_SET); } case PRUNE_UNUSED -> { if (pruneUnused != null) throw new JsonParseException("Unexpected duplicate \"" + PRUNE_UNUSED + "\" in Resclone config"); pruneUnused = reader.nextBoolean(); } default -> throw new JsonParseException("Unexpected element: \"" + name + "\" in Resclone config"); } } reader.endObject(); if (packs == null) throw new JsonParseException("Expected Resclone config object to contain packs"); if (pruneUnused == null) { pruneUnused = true; updateRequired = true; } RescloneConfig.packs = packs; RescloneConfig.pruneUnused = pruneUnused; } else throw new JsonParseException("Expected Resclone config to be an object or array"); } if (updateRequired) write(path); } private static void write(Path path) throws IOException { try (BufferedWriter bw = Files.newBufferedWriter(path); JsonWriter writer = GsonHolders.CONFIG.getGson().newJsonWriter(bw)) { writer.beginObject() .comment("The packs to be loaded by resclone") .name(PACKS); GsonHolders.CONFIG.getGson().toJson(packs, META_SET, writer); writer.comment("Whether to prune unused packs from the cache") .name(PRUNE_UNUSED) .value(pruneUnused) .endObject(); } } static { Path path = Resclone.getConfigPath().resolve("config.json"); DSL.create(Resclone.MOD_ID).register(builder -> builder.setLoadMethod(configInstance -> { try { load(path); } catch (IOException e) { Resclone.LOGGER.error("Could not load config", e); } }).setWriteMethod(configInstance -> { try { write(path); } catch (IOException e) { Resclone.LOGGER.error("Could not write config", e); } }).setPath(path) .>value(PACKS, new HashSet<>(), Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, io.gitlab.jfronny.libjf.config.api.v1.type.Type.ofClass(META_SET), 100, () -> packs, p -> packs = p) .value(PRUNE_UNUSED, pruneUnused, () -> pruneUnused, p -> pruneUnused = p) ).load(); } @Override public void register(DSL.Defaulted dsl) { } }