package io.gitlab.jfronny.respackopts.mixin; import com.google.gson.*; import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.data.Respackmeta; import net.minecraft.resource.ResourcePackManager; import net.minecraft.resource.ResourcePackProfile; import net.minecraft.resource.ResourceType; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.TreeSet; @Mixin(ResourcePackManager.class) public class ResourcePackManagerMixin { @Shadow private Map profiles; @Inject(at = @At("TAIL"), method = "scanPacks()V") private void scanPacks(CallbackInfo info) { profiles.forEach((s, v) -> { if (respackopts$hasMetadata(v, "conf.json")) { try { boolean overwriteData = false; Respackmeta conf = Respackopts.g.fromJson(respackopts$readMetadata(v, "conf.json", Respackopts.g), Respackmeta.class); if (!Respackopts.boolVals.containsKey(conf.id)) Respackopts.boolVals.put(conf.id, new HashMap<>()); if (!Respackopts.numVals.containsKey(conf.id)) Respackopts.numVals.put(conf.id, new HashMap<>()); if (!Respackopts.strVals.containsKey(conf.id)) Respackopts.strVals.put(conf.id, new HashMap<>()); if (!Respackopts.enumKeys.containsKey(conf.id)) Respackopts.enumKeys.put(conf.id, new HashMap<>()); if (Respackopts.metaVersion.equals(conf.version)) { overwriteData |= !Respackopts.resPackMetas.containsKey(v.getDisplayName().asString()); Respackopts.resPackMetas.put(v.getDisplayName().asString(), conf); } else { System.err.println(s + " was not loaded as it specifies a different respackopts version than is installed"); return; } respackopts$registerFields(conf.conf, conf.id, ""); if (overwriteData) { Respackopts.load(conf.id); } } catch (Throwable e) { e.printStackTrace(); } } }); } private void respackopts$registerFields(JsonObject data, String id, String keyPrefix) { for (Map.Entry entry : data.entrySet()) { String n = keyPrefix + entry.getKey(); JsonElement e = entry.getValue(); if (e.isJsonPrimitive()) { JsonPrimitive p = e.getAsJsonPrimitive(); if (p.isBoolean()) { if (!Respackopts.boolVals.get(id).containsKey(n)) Respackopts.boolVals.get(id).put(n, p.getAsBoolean()); } else if (p.isNumber()) { if (!Respackopts.numVals.get(id).containsKey(n)) Respackopts.numVals.get(id).put(n, p.getAsDouble()); } else if (p.isString()) { if (!Respackopts.strVals.get(id).containsKey(n)) Respackopts.strVals.get(id).put(n, p.getAsString()); } } else if (e.isJsonArray()) { JsonArray a = e.getAsJsonArray(); for (JsonElement element : a) { if (!element.isJsonPrimitive()) { System.err.println("[respackopts] Unsupported non-primitive datatype"); continue; } if (!Respackopts.enumKeys.get(id).containsKey(n)) { Respackopts.enumKeys.get(id).put(n, new TreeSet<>()); } JsonPrimitive p = element.getAsJsonPrimitive(); if (!p.isString()) { System.err.println("[respackopts] Unsupported non-string enum key"); continue; } String b = p.getAsString(); if (b.contains(":") || b.contains(".") || b.contains("_")) { System.err.println(b + " contains invalid characters"); continue; } Respackopts.enumKeys.get(id).get(n).add(b); } if (!Respackopts.numVals.get(id).containsKey(n)) { Respackopts.numVals.get(id).put(n, 0d); } } else if (e.isJsonNull()) { System.out.println("[respackopts] Config definition contains null, skipping that entry"); } else if (e.isJsonObject()) { respackopts$registerFields(e.getAsJsonObject(), id, n + "."); } else { System.err.println("[respackopts] Unsupported non-primitive datatype"); } } } private boolean respackopts$hasMetadata(ResourcePackProfile v, String fname) { return v.createResourcePack().contains(ResourceType.CLIENT_RESOURCES, new Identifier(Respackopts.ID, fname)); } private JsonObject respackopts$readMetadata(ResourcePackProfile v, String fname, Gson g) throws IOException { InputStream is = v.createResourcePack().open(ResourceType.CLIENT_RESOURCES, new Identifier(Respackopts.ID, fname)); ByteArrayOutputStream bais = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; while ((length = is.read(buffer)) != -1) { bais.write(buffer, 0, length); } return g.fromJson(bais.toString(), JsonElement.class).getAsJsonObject(); } }