Respackopts/src/main/java/io/gitlab/jfronny/respackopts/mixin/ResourcePackManagerMixin.java
2020-12-28 12:12:59 +01:00

159 lines
7.4 KiB
Java

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.LinkedHashSet;
import java.util.Map;
@Mixin(ResourcePackManager.class)
public class ResourcePackManagerMixin {
@Shadow private Map<String, ResourcePackProfile> profiles;
@Inject(at = @At("TAIL"), method = "scanPacks()V")
private void scanPacks(CallbackInfo info) {
profiles.forEach((s, v) -> {
if (respackopts$hasMetadata(v, "conf.json")) {
try {
Respackmeta conf = Respackopts.g.fromJson(respackopts$readMetadata(v, "conf.json", Respackopts.g), Respackmeta.class);
if (!Respackopts.metaVersion.equals(conf.version)) {
Respackopts.logger.error(s + " was not loaded as it specifies a different respackopts version than is installed");
return;
}
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<>());
Respackopts.resPackMetas.put(v.getDisplayName().asString(), conf);
respackopts$registerFields(conf.conf, conf.id, "");
Respackopts.load(conf.id);
} catch (Throwable e) {
e.printStackTrace();
}
}
});
}
private void respackopts$registerFields(JsonObject data, String id, String keyPrefix) {
//Slider
if (data.entrySet().stream().allMatch(s -> "default".equals(s.getKey()) || "min".equals(s.getKey()) || "max".equals(s.getKey())))
{
JsonElement def = data.get("default");
JsonElement min = data.get("min");
JsonElement max = data.get("max");
if (def.isJsonPrimitive() && def.getAsJsonPrimitive().isNumber()
&& min.isJsonPrimitive() && min.getAsJsonPrimitive().isNumber()
&& max.isJsonPrimitive() && max.getAsJsonPrimitive().isNumber()) {
double defV = def.getAsNumber().doubleValue();
double minV = min.getAsNumber().doubleValue();
double maxV = max.getAsNumber().doubleValue();
if (defV < minV || defV > maxV) {
Respackopts.logger.error("Default value out of range in slider definition " + id);
}
else if (respackopts$isWhole(defV) && respackopts$isWhole(minV) && respackopts$isWhole(maxV)) {
Respackopts.numVals.get(id).put(keyPrefix, defV);
}
else {
Respackopts.logger.error("Expected whole number in slider definition " + id);
}
}
else {
Respackopts.logger.error("Expected numeric values in slider definition " + id);
}
return;
}
//Normal object
for (Map.Entry<String, JsonElement> entry : data.entrySet()) {
String n = ("".equals(keyPrefix) ? "" : 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()) {
Respackopts.logger.error("Unsupported non-primitive datatype in enum definition");
continue;
}
if (!Respackopts.enumKeys.get(id).containsKey(n)) {
Respackopts.enumKeys.get(id).put(n, new LinkedHashSet<>());
}
JsonPrimitive p = element.getAsJsonPrimitive();
if (!p.isString()) {
Respackopts.logger.error("Unsupported non-string enum key");
continue;
}
String b = p.getAsString();
if (b.contains(":") || b.contains(".") || b.contains("_")) {
Respackopts.logger.error(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()) {
Respackopts.logger.error("Config definition contains null, skipping that entry");
}
else if (e.isJsonObject()) {
respackopts$registerFields(e.getAsJsonObject(), id, n);
}
else {
Respackopts.logger.error("Unsupported non-primitive datatype");
}
}
}
private boolean respackopts$isWhole(double v) {
return v == Math.floor(v) && !Double.isInfinite(v);
}
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();
}
}