diff --git a/run/resourcepacks/testpack/assets/respackopts/conf.json b/run/resourcepacks/testpack/assets/respackopts/conf.json index ad0754a..315d212 100644 --- a/run/resourcepacks/testpack/assets/respackopts/conf.json +++ b/run/resourcepacks/testpack/assets/respackopts/conf.json @@ -1,6 +1,7 @@ { "id": "lumi", "version": 5, + "capabilities": ["FileFilter", "DirFilter", "DirFilterAdditive"], "conf": { "tonemap": [ "default", diff --git a/src/main/java/io/gitlab/jfronny/respackopts/Respackopts.java b/src/main/java/io/gitlab/jfronny/respackopts/Respackopts.java index 7da56f2..5d1df46 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/Respackopts.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/Respackopts.java @@ -3,14 +3,15 @@ package io.gitlab.jfronny.respackopts; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.gitlab.jfronny.libjf.data.WrappedPack; +import io.gitlab.jfronny.respackopts.data.condition.Condition; +import io.gitlab.jfronny.respackopts.filters.DirFilterEventImpl; import io.gitlab.jfronny.respackopts.util.RpoCommand; import io.gitlab.jfronny.respackopts.data.DirRpo; import io.gitlab.jfronny.respackopts.data.PackCapability; import io.gitlab.jfronny.respackopts.data.PackMeta; import io.gitlab.jfronny.respackopts.data.FileRpo; import io.gitlab.jfronny.respackopts.data.entry.*; -import io.gitlab.jfronny.respackopts.filters.DirFilterProvider; -import io.gitlab.jfronny.respackopts.filters.FileFilterProvider; +import io.gitlab.jfronny.respackopts.filters.FileFilterEventImpl; import io.gitlab.jfronny.respackopts.gson.*; import io.gitlab.jfronny.respackopts.util.GuiFactory; import meteordevelopment.starscript.Script; @@ -57,7 +58,7 @@ public class Respackopts implements ClientModInitializer { public static final Gson GSON; public static GuiFactory factory = new GuiFactory(); - public static boolean forceRespackReload = false; + public static boolean forcePackReload = false; static { GSON = new GsonBuilder() @@ -68,6 +69,7 @@ public class Respackopts implements ClientModInitializer { .registerTypeAdapter(Script.class, new ScriptDeserializer()) .registerTypeAdapter(FileRpo.class, new RpoDeserializer()) .registerTypeAdapter(DirRpo.class, new DirRpoDeserializer()) + .registerTypeAdapter(Condition.class, new ConditionDeserializer()) .setPrettyPrinting() .create(); try { @@ -107,8 +109,8 @@ public class Respackopts implements ClientModInitializer { STAR_SCRIPT.set(sanitizeString(e.getKey()), () -> e.getValue().buildStarscript()); } }); - DirFilterProvider.init(); - FileFilterProvider.init(); + DirFilterEventImpl.init(); + FileFilterEventImpl.init(); RpoCommand.register(); } diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/DirRpo.java b/src/main/java/io/gitlab/jfronny/respackopts/data/DirRpo.java index cec3482..0f03c8a 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/data/DirRpo.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/DirRpo.java @@ -1,10 +1,10 @@ package io.gitlab.jfronny.respackopts.data; -import com.google.gson.JsonArray; import io.gitlab.jfronny.libjf.gson.GsonHidden; +import io.gitlab.jfronny.respackopts.data.condition.Condition; public class DirRpo { - public JsonArray conditions; + public Condition conditions; public String fallback; @GsonHidden diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/FileRpo.java b/src/main/java/io/gitlab/jfronny/respackopts/data/FileRpo.java index d4d5ed4..b485049 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/data/FileRpo.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/FileRpo.java @@ -1,13 +1,13 @@ package io.gitlab.jfronny.respackopts.data; -import com.google.gson.JsonArray; +import io.gitlab.jfronny.respackopts.data.condition.Condition; import meteordevelopment.starscript.Script; import java.util.List; import java.util.Map; public class FileRpo { - public JsonArray conditions; + public Condition conditions; public List fallbacks; public Map expansions; } diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/condition/AndConditionFactory.java b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/AndConditionFactory.java new file mode 100644 index 0000000..b56c2bf --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/AndConditionFactory.java @@ -0,0 +1,21 @@ +package io.gitlab.jfronny.respackopts.data.condition; + +import java.util.Set; + +public class AndConditionFactory implements CollectingConditionFactory { + @Override + public Condition build(Set conditions) { + return packId -> { + for (Condition condition : conditions) { + if (!condition.evaluate(packId)) + return false; + } + return true; + }; + } + + @Override + public Set getNames() { + return Set.of("and", "add", "&"); + } +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/condition/BooleanCondition.java b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/BooleanCondition.java new file mode 100644 index 0000000..1f7fe59 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/BooleanCondition.java @@ -0,0 +1,8 @@ +package io.gitlab.jfronny.respackopts.data.condition; + +public record BooleanCondition(boolean value) implements Condition { + @Override + public boolean evaluate(String packId) { + return value; + } +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/condition/CollectingConditionFactory.java b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/CollectingConditionFactory.java new file mode 100644 index 0000000..26c16b5 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/CollectingConditionFactory.java @@ -0,0 +1,8 @@ +package io.gitlab.jfronny.respackopts.data.condition; + +import java.util.Set; + +public interface CollectingConditionFactory { + Condition build(Set conditions); + Set getNames(); +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/condition/Condition.java b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/Condition.java new file mode 100644 index 0000000..06f71ab --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/Condition.java @@ -0,0 +1,7 @@ +package io.gitlab.jfronny.respackopts.data.condition; + +import io.gitlab.jfronny.respackopts.util.RpoFormatException; + +public interface Condition { + boolean evaluate(String packId) throws RpoFormatException; +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/condition/EqualityConditionFactory.java b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/EqualityConditionFactory.java new file mode 100644 index 0000000..abcf007 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/EqualityConditionFactory.java @@ -0,0 +1,24 @@ +package io.gitlab.jfronny.respackopts.data.condition; + +import java.util.Set; + +public class EqualityConditionFactory implements CollectingConditionFactory { + @Override + public Condition build(Set conditions) { + return packId -> { + Boolean b = null; + for (Condition condition : conditions) { + if (b == null) + b = condition.evaluate(packId); + else if (b != condition.evaluate(packId)) + return false; + } + return true; + }; + } + + @Override + public Set getNames() { + return Set.of("==", "=", "equal", "eq"); + } +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/condition/NorConditionFactory.java b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/NorConditionFactory.java new file mode 100644 index 0000000..b4098ef --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/NorConditionFactory.java @@ -0,0 +1,21 @@ +package io.gitlab.jfronny.respackopts.data.condition; + +import java.util.Set; + +public class NorConditionFactory implements CollectingConditionFactory { + @Override + public Condition build(Set conditions) { + return packId -> { + for (Condition condition : conditions) { + if (condition.evaluate(packId)) + return false; + } + return true; + }; + } + + @Override + public Set getNames() { + return Set.of("not", "nor", "!"); + } +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/condition/OrConditionFactory.java b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/OrConditionFactory.java new file mode 100644 index 0000000..7d5266f --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/OrConditionFactory.java @@ -0,0 +1,21 @@ +package io.gitlab.jfronny.respackopts.data.condition; + +import java.util.Set; + +public class OrConditionFactory implements CollectingConditionFactory { + @Override + public Condition build(Set conditions) { + return packId -> { + for (Condition condition : conditions) { + if (condition.evaluate(packId)) + return true; + } + return false; + }; + } + + @Override + public Set getNames() { + return Set.of("or", "|"); + } +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/condition/RpoBooleanCondition.java b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/RpoBooleanCondition.java new file mode 100644 index 0000000..581d88a --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/RpoBooleanCondition.java @@ -0,0 +1,36 @@ +package io.gitlab.jfronny.respackopts.data.condition; + +import com.google.gson.JsonParseException; +import io.gitlab.jfronny.respackopts.Respackopts; +import io.gitlab.jfronny.respackopts.data.entry.ConfigBranch; +import io.gitlab.jfronny.respackopts.util.RpoFormatException; + +import java.util.Map; +import java.util.Objects; + +public record RpoBooleanCondition(String name) implements Condition { + public RpoBooleanCondition { + if (name == null) + throw new JsonParseException("Condition must not be null"); + } + + @Override + public boolean evaluate(String packId) throws RpoFormatException { + String condition = name; + if (!condition.contains(":")) { + condition = packId + ":" + condition; + } + String sourcePack = condition.split(":")[0]; + condition = condition.substring(condition.indexOf(':') + 1); + for (Map.Entry e : Respackopts.CONFIG_BRANCH.entrySet()) { + if (Objects.equals(e.getKey(), sourcePack)) { + try { + return e.getValue().getBoolean(condition); + } catch (RpoFormatException ex) { + throw new RpoFormatException("Could not get value", ex); + } + } + } + throw new RpoFormatException("Could not find pack with specified ID"); + } +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/data/condition/XorConditionFactory.java b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/XorConditionFactory.java new file mode 100644 index 0000000..dd2ef06 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/data/condition/XorConditionFactory.java @@ -0,0 +1,22 @@ +package io.gitlab.jfronny.respackopts.data.condition; + +import java.util.Set; + +public class XorConditionFactory implements CollectingConditionFactory { + @Override + public Condition build(Set conditions) { + return packId -> { + boolean bl = false; + for (Condition condition : conditions) { + if (condition.evaluate(packId)) + bl = !bl; + } + return bl; + }; + } + + @Override + public Set getNames() { + return Set.of("^", "xor"); + } +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterProvider.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterEventImpl.java similarity index 94% rename from src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterProvider.java rename to src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterEventImpl.java index ac35c01..b7a3435 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterProvider.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/DirFilterEventImpl.java @@ -7,12 +7,11 @@ import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.data.DirRpo; import io.gitlab.jfronny.respackopts.data.PackCapability; import io.gitlab.jfronny.respackopts.util.RpoFormatException; -import io.gitlab.jfronny.respackopts.filters.conditions.ConditionEvaluator; import net.minecraft.util.Identifier; import java.io.*; -public class DirFilterProvider { +public class DirFilterEventImpl { public static void init() { UserResourceEvents.OPEN.register((type, id, previous, pack) -> { if (!Respackopts.hasCapability(pack, PackCapability.DirFilter)) @@ -33,7 +32,6 @@ public class DirFilterProvider { if (!Respackopts.hasCapability(pack, PackCapability.DirFilter)) return previous; boolean dirFilterAdditive = Respackopts.hasCapability(pack, PackCapability.DirFilterAdditive); - //TODO support files that weren't there at the original location for (Identifier identifier : previous) { String path = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath(); DirRpo rpo = findDirRpo(pack, path); @@ -46,7 +44,7 @@ public class DirFilterProvider { String[] s = path.split("/", 3); if (s.length == 3) { ResourcePath rp = new ResourcePath(path); - //TODO this implementation is stupid + //TODO improve this impl (used for files that aren't at the original location for (Identifier resource : pack.findResources(rp.getType(), rp.getId().getNamespace(), rp.getId().getPath(), maxDepth, (a) -> true)) { String p = type.getDirectory() + "/" + resource.getNamespace() + "/" + resource.getPath(); p = p.replace(rpo.fallback, rpo.path + "/"); @@ -86,7 +84,7 @@ public class DirFilterProvider { if (rpo.conditions == null) return false; try { - return !ConditionEvaluator.evaluate(rpo.conditions, packId); + return !rpo.conditions.evaluate(packId); } catch (RpoFormatException e) { Respackopts.LOGGER.error("Couldn't parse dir conditions", e); } diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterProvider.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterEventImpl.java similarity index 71% rename from src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterProvider.java rename to src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterEventImpl.java index 24b5d40..0c506b5 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterProvider.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/FileFilterEventImpl.java @@ -5,9 +5,9 @@ import io.gitlab.jfronny.libjf.data.UserResourceEvents; import io.gitlab.jfronny.libjf.data.WrappedPack; import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.data.PackCapability; -import io.gitlab.jfronny.respackopts.filters.conditions.ResourcePackFilter; -import io.gitlab.jfronny.respackopts.filters.expansion.DataExpander; -import io.gitlab.jfronny.respackopts.filters.fallback.FallbackFilter; +import io.gitlab.jfronny.respackopts.filters.util.FileExclusionProvider; +import io.gitlab.jfronny.respackopts.filters.util.FileExpansionProvider; +import io.gitlab.jfronny.respackopts.filters.util.FileFallbackProvider; import net.minecraft.resource.AbstractFileResourcePack; import net.minecraft.util.Identifier; @@ -15,7 +15,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; -public class FileFilterProvider { +public class FileFilterEventImpl { public static void init() { AtomicBoolean containsFileWasFallback = new AtomicBoolean(false); UserResourceEvents.OPEN.register((type, id, previous, pack) -> { @@ -24,8 +24,8 @@ public class FileFilterProvider { IOException ex = new FileNotFoundException(); if (pack.contains(type, id)) { if (containsFileWasFallback.get()) - return FallbackFilter.getReplacement(pack, name, ex); - return DataExpander.replace(previous, pack, name, ex); + return FileFallbackProvider.getReplacement(pack, name, ex); + return FileExpansionProvider.replace(previous, pack, name, ex); } throw ex; }); @@ -33,9 +33,9 @@ public class FileFilterProvider { // Warning: the Identifiers here DON'T CONTAIN THE TYPE! // Therefore, it needs to be added when calling a method that generates a ResourcePath! if (skip(pack)) return previous; - previous.removeIf(s -> ResourcePackFilter.fileHidden(pack, type.getDirectory() + "/" + s.getNamespace() + "/" + s.getPath()) && !FallbackFilter.fileVisible(pack, namespace)); + previous.removeIf(s -> FileExclusionProvider.fileHidden(pack, type.getDirectory() + "/" + s.getNamespace() + "/" + s.getPath()) && !FileFallbackProvider.fileVisible(pack, namespace)); // Completion of the path is handled separately here - FallbackFilter.addFallbackResources(pack, previous, namespace, type); + FileFallbackProvider.addFallbackResources(pack, previous, namespace, type); return previous; }); UserResourceEvents.CONTAINS.register((type, id, previous, pack) -> { @@ -43,8 +43,8 @@ public class FileFilterProvider { containsFileWasFallback.set(false); String name = new ResourcePath(type, id).getName(); if (previous) { - if (ResourcePackFilter.fileHidden(pack, name)) { - if (FallbackFilter.fileVisible(pack, name)) { + if (FileExclusionProvider.fileHidden(pack, name)) { + if (FileFallbackProvider.fileVisible(pack, name)) { containsFileWasFallback.set(true); } else { return false; @@ -53,7 +53,7 @@ public class FileFilterProvider { return true; } else { - if (pack.getUnderlying().contains(type, new Identifier(id.getNamespace(), id.getPath() + ".rpo")) && FallbackFilter.fileVisible(pack, name)) { + if (pack.getUnderlying().contains(type, new Identifier(id.getNamespace(), id.getPath() + ".rpo")) && FileFallbackProvider.fileVisible(pack, name)) { containsFileWasFallback.set(true); return true; } diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/AndCondition.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/AndCondition.java deleted file mode 100644 index 0486243..0000000 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/AndCondition.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.gitlab.jfronny.respackopts.filters.conditions; - -import com.google.gson.JsonElement; -import io.gitlab.jfronny.respackopts.util.RpoFormatException; - -import java.util.LinkedHashSet; -import java.util.Set; - -public class AndCondition implements Condition { - @Override - public boolean evaluate(JsonElement node, String packId) throws RpoFormatException { - if (!node.isJsonArray()) - throw new RpoFormatException("\"and\" condition requires an array of conditions"); - for (JsonElement jsonElement : node.getAsJsonArray()) { - if (!ConditionEvaluator.evaluate(jsonElement, packId)) - return false; - } - return true; - } - - @Override - public Set getKeys() { - Set strings = new LinkedHashSet<>(); - strings.add("add"); - strings.add("&"); - return strings; - } -} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/Condition.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/Condition.java deleted file mode 100644 index 2ab051e..0000000 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/Condition.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.gitlab.jfronny.respackopts.filters.conditions; - -import com.google.gson.JsonElement; -import io.gitlab.jfronny.respackopts.util.RpoFormatException; - -import java.util.Set; - -public interface Condition { - boolean evaluate(JsonElement node, String packId) throws RpoFormatException; - Set getKeys(); -} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/ConditionEvaluator.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/ConditionEvaluator.java deleted file mode 100644 index 64fa9ed..0000000 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/ConditionEvaluator.java +++ /dev/null @@ -1,70 +0,0 @@ -package io.gitlab.jfronny.respackopts.filters.conditions; - -import com.google.gson.JsonElement; -import io.gitlab.jfronny.respackopts.Respackopts; -import io.gitlab.jfronny.respackopts.util.RpoFormatException; -import io.gitlab.jfronny.respackopts.data.entry.ConfigBranch; - -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -public class ConditionEvaluator { - private static final Set conditions; - static { - conditions = new LinkedHashSet<>(); - conditions.add(new AndCondition()); - conditions.add(new OrCondition()); - conditions.add(new XorCondition()); - conditions.add(new EqualityCondition()); - conditions.add(new NorCondition()); - } - - public static boolean evaluate(JsonElement condition, String packId) throws RpoFormatException { - if (condition.isJsonPrimitive() && condition.getAsJsonPrimitive().isString()) - return evaluate(condition.getAsString(), packId); - if (condition.isJsonObject() && condition.getAsJsonObject().size() == 1) { - for (Map.Entry entry : condition.getAsJsonObject().entrySet()) { - for (Condition c : conditions) { - if (c.getKeys().contains(entry.getKey())) { - return c.evaluate(entry.getValue(), packId); - } - } - throw new RpoFormatException("Could not find condition: " + entry.getKey()); - } - } - if (condition.isJsonArray()) { - for (JsonElement element : condition.getAsJsonArray()) { - if (!evaluate(element, packId)) - return false; - } - return true; - } - throw new RpoFormatException("Condition entries may only be json objects containing one key and one value or strings"); - } - - public static boolean evaluate(String condition, String packId) throws RpoFormatException { - if (condition == null) { - throw new RpoFormatException("Condition must not be null"); - } - - if ("true".equals(condition)) - return true; - if ("false".equals(condition)) - return false; - - if (!condition.contains(":")) { - condition = packId + ":" + condition; - } - - String sourcePack = condition.split(":")[0]; - String name = condition.substring(condition.indexOf(':') + 1); - for (Map.Entry e : Respackopts.CONFIG_BRANCH.entrySet()) { - if (Objects.equals(e.getKey(), sourcePack)) { - return e.getValue().getBoolean(name); - } - } - throw new RpoFormatException("Could not find pack with specified ID"); - } -} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/EqualityCondition.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/EqualityCondition.java deleted file mode 100644 index fc154c3..0000000 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/EqualityCondition.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.gitlab.jfronny.respackopts.filters.conditions; - -import com.google.gson.JsonElement; -import io.gitlab.jfronny.respackopts.util.RpoFormatException; - -import java.util.LinkedHashSet; -import java.util.Optional; -import java.util.Set; - -public class EqualityCondition implements Condition { - @Override - public boolean evaluate(JsonElement node, String packId) throws RpoFormatException { - if (!node.isJsonArray()) - throw new RpoFormatException("\"equal\" condition requires an array of conditions"); - Optional v = Optional.empty(); - for (JsonElement jsonElement : node.getAsJsonArray()) { - boolean current = ConditionEvaluator.evaluate(jsonElement, packId); - if (v.isEmpty()) - v = Optional.of(current); - if (current != v.get()) - return false; - } - return true; - } - - @Override - public Set getKeys() { - Set strings = new LinkedHashSet<>(); - strings.add("=="); - strings.add("="); - strings.add("equal"); - strings.add("eq"); - return strings; - } -} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/NorCondition.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/NorCondition.java deleted file mode 100644 index fbd5f66..0000000 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/NorCondition.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.gitlab.jfronny.respackopts.filters.conditions; - -import com.google.gson.JsonElement; -import io.gitlab.jfronny.respackopts.util.RpoFormatException; - -import java.util.LinkedHashSet; -import java.util.Set; - -public class NorCondition implements Condition { - @Override - public boolean evaluate(JsonElement node, String packId) throws RpoFormatException { - if (node.isJsonPrimitive() && node.getAsJsonPrimitive().isString()) { - return !ConditionEvaluator.evaluate(node.getAsString(), packId); - } - if (!node.isJsonArray()) - throw new RpoFormatException("\"not\"/\"nor\" condition requires an array of conditions"); - for (JsonElement jsonElement : node.getAsJsonArray()) { - if (ConditionEvaluator.evaluate(jsonElement, packId)) - return false; - } - return true; - } - - @Override - public Set getKeys() { - Set strings = new LinkedHashSet<>(); - strings.add("not"); - strings.add("nor"); - strings.add("!"); - return strings; - } -} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/OrCondition.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/OrCondition.java deleted file mode 100644 index 5548706..0000000 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/OrCondition.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.gitlab.jfronny.respackopts.filters.conditions; - -import com.google.gson.JsonElement; -import io.gitlab.jfronny.respackopts.util.RpoFormatException; - -import java.util.LinkedHashSet; -import java.util.Set; - -public class OrCondition implements Condition { - @Override - public boolean evaluate(JsonElement node, String packId) throws RpoFormatException { - if (!node.isJsonArray()) - throw new RpoFormatException("\"or\" condition requires an array of conditions"); - for (JsonElement jsonElement : node.getAsJsonArray()) { - if (ConditionEvaluator.evaluate(jsonElement, packId)) - return true; - } - return false; - } - - @Override - public Set getKeys() { - Set strings = new LinkedHashSet<>(); - strings.add("or"); - strings.add("|"); - return strings; - } -} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/XorCondition.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/XorCondition.java deleted file mode 100644 index 2c01604..0000000 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/XorCondition.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.gitlab.jfronny.respackopts.filters.conditions; - -import com.google.gson.JsonElement; -import io.gitlab.jfronny.respackopts.util.RpoFormatException; - -import java.util.LinkedHashSet; -import java.util.Set; - -public class XorCondition implements Condition { - @Override - public boolean evaluate(JsonElement node, String packId) throws RpoFormatException { - if (!node.isJsonArray()) - throw new RpoFormatException("\"xor\" condition requires an array of conditions"); - boolean bl = false; - for (JsonElement jsonElement : node.getAsJsonArray()) { - if (ConditionEvaluator.evaluate(jsonElement, packId)) - bl = !bl; - } - return bl; - } - - @Override - public Set getKeys() { - Set strings = new LinkedHashSet<>(); - strings.add("^"); - strings.add("xor"); - return strings; - } -} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/ResourcePackFilter.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/util/FileExclusionProvider.java similarity index 87% rename from src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/ResourcePackFilter.java rename to src/main/java/io/gitlab/jfronny/respackopts/filters/util/FileExclusionProvider.java index cd4df08..e58fffe 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/conditions/ResourcePackFilter.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/util/FileExclusionProvider.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.respackopts.filters.conditions; +package io.gitlab.jfronny.respackopts.filters.util; import io.gitlab.jfronny.libjf.data.ResourcePath; import io.gitlab.jfronny.libjf.data.WrappedPack; @@ -9,7 +9,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -public class ResourcePackFilter { +public class FileExclusionProvider { public static boolean fileHidden(WrappedPack pack, String name) { if (name.endsWith(Respackopts.FILE_EXTENSION)) return false; @@ -26,7 +26,7 @@ public class ResourcePackFilter { FileRpo rpo = Respackopts.GSON.fromJson(w, FileRpo.class); if (rpo.conditions == null) return false; - return !ConditionEvaluator.evaluate(rpo.conditions, Respackopts.getId(pack)); + return !rpo.conditions.evaluate(Respackopts.getId(pack)); } catch (Throwable e) { Respackopts.LOGGER.error("Could not load RPO file " + name, e); diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/expansion/DataExpander.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/util/FileExpansionProvider.java similarity index 95% rename from src/main/java/io/gitlab/jfronny/respackopts/filters/expansion/DataExpander.java rename to src/main/java/io/gitlab/jfronny/respackopts/filters/util/FileExpansionProvider.java index 2951633..2264a91 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/expansion/DataExpander.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/util/FileExpansionProvider.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.respackopts.filters.expansion; +package io.gitlab.jfronny.respackopts.filters.util; import io.gitlab.jfronny.libjf.data.ResourcePath; import io.gitlab.jfronny.libjf.data.WrappedPack; @@ -9,7 +9,7 @@ import meteordevelopment.starscript.Script; import java.io.*; import java.util.Map; -public class DataExpander { +public class FileExpansionProvider { public static synchronized InputStream replace(InputStream is, Map expansions) throws IOException { String s = new String(is.readAllBytes()); for (Map.Entry entry : expansions.entrySet()) { diff --git a/src/main/java/io/gitlab/jfronny/respackopts/filters/fallback/FallbackFilter.java b/src/main/java/io/gitlab/jfronny/respackopts/filters/util/FileFallbackProvider.java similarity index 97% rename from src/main/java/io/gitlab/jfronny/respackopts/filters/fallback/FallbackFilter.java rename to src/main/java/io/gitlab/jfronny/respackopts/filters/util/FileFallbackProvider.java index adc2a9e..371b432 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/filters/fallback/FallbackFilter.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/filters/util/FileFallbackProvider.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.respackopts.filters.fallback; +package io.gitlab.jfronny.respackopts.filters.util; import io.gitlab.jfronny.libjf.data.ResourcePath; import io.gitlab.jfronny.libjf.data.WrappedPack; @@ -14,7 +14,7 @@ import java.io.Reader; import java.util.Collection; import java.util.List; -public class FallbackFilter { +public class FileFallbackProvider { public static boolean fileVisible(WrappedPack pack, String name) { if (name.endsWith(Respackopts.FILE_EXTENSION)) return false; diff --git a/src/main/java/io/gitlab/jfronny/respackopts/gson/ConditionDeserializer.java b/src/main/java/io/gitlab/jfronny/respackopts/gson/ConditionDeserializer.java new file mode 100644 index 0000000..a17b62e --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/respackopts/gson/ConditionDeserializer.java @@ -0,0 +1,57 @@ +package io.gitlab.jfronny.respackopts.gson; + +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; +import io.gitlab.jfronny.respackopts.data.condition.*; + +import java.lang.reflect.Type; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +public class ConditionDeserializer implements JsonDeserializer { + private static final AndConditionFactory and = new AndConditionFactory(); + private static final Set factories = Set.of( + and, + new EqualityConditionFactory(), + new NorConditionFactory(), + new OrConditionFactory(), + new XorConditionFactory() + ); + private static final Type conditionSetType = new TypeToken>(){}.getType(); + + @Override + public Condition deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonObject()) { + JsonObject jo = json.getAsJsonObject(); + if (jo.size() != 1) + throw new JsonParseException("More than one key in a condition object"); + for (Map.Entry entry : jo.entrySet()) { + String name = entry.getKey(); + for (CollectingConditionFactory factory : factories) { + if (factory.getNames().contains(name)) + return factory.build(context.deserialize(entry.getValue(), conditionSetType)); + } + throw new JsonParseException("Unknown condition type: " + name); + } + } + else if (json.isJsonArray()) { + return and.build(context.deserialize(json, conditionSetType)); + } + else if (json.isJsonPrimitive()) { + JsonPrimitive pr = json.getAsJsonPrimitive(); + if (pr.isString()) { + String name = pr.getAsString(); + if (name.toLowerCase(Locale.ROOT).equals("true")) + return new BooleanCondition(true); + if (name.toLowerCase(Locale.ROOT).equals("false")) + return new BooleanCondition(false); + return new RpoBooleanCondition(name); + } + else if (pr.isBoolean()) { + return new BooleanCondition(pr.getAsBoolean()); + } + } + throw new JsonParseException("Invalid data type for condition"); + } +} diff --git a/src/main/java/io/gitlab/jfronny/respackopts/gson/DirRpoDeserializer.java b/src/main/java/io/gitlab/jfronny/respackopts/gson/DirRpoDeserializer.java index 774651d..e628c43 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/gson/DirRpoDeserializer.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/gson/DirRpoDeserializer.java @@ -2,6 +2,7 @@ package io.gitlab.jfronny.respackopts.gson; import com.google.gson.*; import io.gitlab.jfronny.respackopts.data.DirRpo; +import io.gitlab.jfronny.respackopts.data.condition.Condition; import java.lang.reflect.Type; import java.util.Map; @@ -16,18 +17,7 @@ public class DirRpoDeserializer implements JsonDeserializer { switch (entry.getKey()) { case "conditions": case "condition": - if (entry.getValue().isJsonArray()) - rpo.conditions = entry.getValue().getAsJsonArray(); - else { - rpo.conditions = new JsonArray(); - if (entry.getValue().isJsonPrimitive() && entry.getValue().getAsJsonPrimitive().isString()) { - rpo.conditions.add(entry.getValue().getAsString()); - } - else if (entry.getValue().isJsonObject()) { - rpo.conditions.add(entry.getValue().getAsJsonObject()); - } - else throw new JsonParseException("Condition type is invalid"); - } + rpo.conditions = context.deserialize(entry.getValue(), Condition.class); break; case "fallbacks": case "fallback": diff --git a/src/main/java/io/gitlab/jfronny/respackopts/gson/RpoDeserializer.java b/src/main/java/io/gitlab/jfronny/respackopts/gson/RpoDeserializer.java index 3e1269c..ea0aa20 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/gson/RpoDeserializer.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/gson/RpoDeserializer.java @@ -3,6 +3,7 @@ package io.gitlab.jfronny.respackopts.gson; import com.google.gson.*; import com.google.gson.reflect.TypeToken; import io.gitlab.jfronny.respackopts.data.FileRpo; +import io.gitlab.jfronny.respackopts.data.condition.Condition; import meteordevelopment.starscript.Script; import java.lang.reflect.Type; @@ -20,18 +21,7 @@ public class RpoDeserializer implements JsonDeserializer { switch (entry.getKey()) { case "conditions": case "condition": - if (entry.getValue().isJsonArray()) - rpo.conditions = entry.getValue().getAsJsonArray(); - else { - rpo.conditions = new JsonArray(); - if (entry.getValue().isJsonPrimitive() && entry.getValue().getAsJsonPrimitive().isString()) { - rpo.conditions.add(entry.getValue().getAsString()); - } - else if (entry.getValue().isJsonObject()) { - rpo.conditions.add(entry.getValue().getAsJsonObject()); - } - else throw new JsonParseException("Condition type is invalid"); - } + rpo.conditions = context.deserialize(entry.getValue(), Condition.class); break; case "fallbacks": case "fallback": diff --git a/src/main/java/io/gitlab/jfronny/respackopts/mixin/OptionsScreenMixin.java b/src/main/java/io/gitlab/jfronny/respackopts/mixin/OptionsScreenMixin.java index 4652b96..da36475 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/mixin/OptionsScreenMixin.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/mixin/OptionsScreenMixin.java @@ -17,8 +17,8 @@ public class OptionsScreenMixin { @Inject(at = @At("HEAD"), method = "refreshResourcePacks(Lnet/minecraft/resource/ResourcePackManager;)V") private void refreshResourcePacks(ResourcePackManager resourcePackManager, CallbackInfo info) { - if (Respackopts.forceRespackReload) { - Respackopts.forceRespackReload = false; + if (Respackopts.forcePackReload) { + Respackopts.forcePackReload = false; this.settings.resourcePacks.clear(); } } diff --git a/src/main/java/io/gitlab/jfronny/respackopts/mixin/ResourcePackManagerMixin.java b/src/main/java/io/gitlab/jfronny/respackopts/mixin/ResourcePackManagerMixin.java index b8d0dad..4e8fa55 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/mixin/ResourcePackManagerMixin.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/mixin/ResourcePackManagerMixin.java @@ -1,7 +1,5 @@ package io.gitlab.jfronny.respackopts.mixin; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.util.MetadataLocateResult; import io.gitlab.jfronny.respackopts.data.PackCapability; @@ -17,9 +15,8 @@ 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.io.InputStreamReader; import java.util.Map; @Mixin(ResourcePackManager.class) @@ -32,8 +29,8 @@ public class ResourcePackManagerMixin { profiles.forEach((s, v) -> { MetadataLocateResult scan = rpo$locateMetadata(v); if (scan.hasMeta()) { - try { - PackMeta conf = Respackopts.GSON.fromJson(rpo$readMetadata(scan), PackMeta.class); + try (InputStream is = scan.pack().open(scan.type(), Respackopts.CONF_ID); InputStreamReader isr = new InputStreamReader(is)) { + PackMeta conf = Respackopts.GSON.fromJson(isr, PackMeta.class); if (Respackopts.META_VERSION < conf.version) { Respackopts.LOGGER.error(s + " was not loaded as it specifies a newer respackopts version than is installed"); return; @@ -68,14 +65,4 @@ public class ResourcePackManagerMixin { return new MetadataLocateResult(pack, false, null); } - private JsonObject rpo$readMetadata(MetadataLocateResult pack) throws IOException { - InputStream is = pack.pack().open(pack.type(), Respackopts.CONF_ID); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int length; - while ((length = is.read(buffer)) != -1) { - os.write(buffer, 0, length); - } - return Respackopts.GSON.fromJson(os.toString(), JsonElement.class).getAsJsonObject(); - } } diff --git a/src/main/java/io/gitlab/jfronny/respackopts/util/GuiFactory.java b/src/main/java/io/gitlab/jfronny/respackopts/util/GuiFactory.java index 1431338..508fee6 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/util/GuiFactory.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/util/GuiFactory.java @@ -59,7 +59,7 @@ public class GuiFactory { ConfigEntryBuilder entryBuilder = builder.entryBuilder(); builder.setSavingRunnable(() -> { Respackopts.save(); - Respackopts.forceRespackReload = true; + Respackopts.forcePackReload = true; DashLoaderCompat.forceReload = true; Respackopts.reloadData(); }); diff --git a/src/main/java/io/gitlab/jfronny/respackopts/util/RpoFormatException.java b/src/main/java/io/gitlab/jfronny/respackopts/util/RpoFormatException.java index ee4a557..963fdb7 100644 --- a/src/main/java/io/gitlab/jfronny/respackopts/util/RpoFormatException.java +++ b/src/main/java/io/gitlab/jfronny/respackopts/util/RpoFormatException.java @@ -4,4 +4,8 @@ public class RpoFormatException extends Exception { public RpoFormatException(String message) { super(message); } + + public RpoFormatException(String message, Throwable cause) { + super(message, cause); + } }