Refactor conditions to use gson

This commit is contained in:
JFronny 2021-09-15 16:45:54 +02:00
parent 8f5014bec0
commit b416df7b0c
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
32 changed files with 272 additions and 308 deletions

View File

@ -1,6 +1,7 @@
{ {
"id": "lumi", "id": "lumi",
"version": 5, "version": 5,
"capabilities": ["FileFilter", "DirFilter", "DirFilterAdditive"],
"conf": { "conf": {
"tonemap": [ "tonemap": [
"default", "default",

View File

@ -3,14 +3,15 @@ package io.gitlab.jfronny.respackopts;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import io.gitlab.jfronny.libjf.data.WrappedPack; 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.util.RpoCommand;
import io.gitlab.jfronny.respackopts.data.DirRpo; import io.gitlab.jfronny.respackopts.data.DirRpo;
import io.gitlab.jfronny.respackopts.data.PackCapability; import io.gitlab.jfronny.respackopts.data.PackCapability;
import io.gitlab.jfronny.respackopts.data.PackMeta; import io.gitlab.jfronny.respackopts.data.PackMeta;
import io.gitlab.jfronny.respackopts.data.FileRpo; import io.gitlab.jfronny.respackopts.data.FileRpo;
import io.gitlab.jfronny.respackopts.data.entry.*; import io.gitlab.jfronny.respackopts.data.entry.*;
import io.gitlab.jfronny.respackopts.filters.DirFilterProvider; import io.gitlab.jfronny.respackopts.filters.FileFilterEventImpl;
import io.gitlab.jfronny.respackopts.filters.FileFilterProvider;
import io.gitlab.jfronny.respackopts.gson.*; import io.gitlab.jfronny.respackopts.gson.*;
import io.gitlab.jfronny.respackopts.util.GuiFactory; import io.gitlab.jfronny.respackopts.util.GuiFactory;
import meteordevelopment.starscript.Script; import meteordevelopment.starscript.Script;
@ -57,7 +58,7 @@ public class Respackopts implements ClientModInitializer {
public static final Gson GSON; public static final Gson GSON;
public static GuiFactory factory = new GuiFactory(); public static GuiFactory factory = new GuiFactory();
public static boolean forceRespackReload = false; public static boolean forcePackReload = false;
static { static {
GSON = new GsonBuilder() GSON = new GsonBuilder()
@ -68,6 +69,7 @@ public class Respackopts implements ClientModInitializer {
.registerTypeAdapter(Script.class, new ScriptDeserializer()) .registerTypeAdapter(Script.class, new ScriptDeserializer())
.registerTypeAdapter(FileRpo.class, new RpoDeserializer()) .registerTypeAdapter(FileRpo.class, new RpoDeserializer())
.registerTypeAdapter(DirRpo.class, new DirRpoDeserializer()) .registerTypeAdapter(DirRpo.class, new DirRpoDeserializer())
.registerTypeAdapter(Condition.class, new ConditionDeserializer())
.setPrettyPrinting() .setPrettyPrinting()
.create(); .create();
try { try {
@ -107,8 +109,8 @@ public class Respackopts implements ClientModInitializer {
STAR_SCRIPT.set(sanitizeString(e.getKey()), () -> e.getValue().buildStarscript()); STAR_SCRIPT.set(sanitizeString(e.getKey()), () -> e.getValue().buildStarscript());
} }
}); });
DirFilterProvider.init(); DirFilterEventImpl.init();
FileFilterProvider.init(); FileFilterEventImpl.init();
RpoCommand.register(); RpoCommand.register();
} }

View File

@ -1,10 +1,10 @@
package io.gitlab.jfronny.respackopts.data; package io.gitlab.jfronny.respackopts.data;
import com.google.gson.JsonArray;
import io.gitlab.jfronny.libjf.gson.GsonHidden; import io.gitlab.jfronny.libjf.gson.GsonHidden;
import io.gitlab.jfronny.respackopts.data.condition.Condition;
public class DirRpo { public class DirRpo {
public JsonArray conditions; public Condition conditions;
public String fallback; public String fallback;
@GsonHidden @GsonHidden

View File

@ -1,13 +1,13 @@
package io.gitlab.jfronny.respackopts.data; package io.gitlab.jfronny.respackopts.data;
import com.google.gson.JsonArray; import io.gitlab.jfronny.respackopts.data.condition.Condition;
import meteordevelopment.starscript.Script; import meteordevelopment.starscript.Script;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class FileRpo { public class FileRpo {
public JsonArray conditions; public Condition conditions;
public List<String> fallbacks; public List<String> fallbacks;
public Map<String, Script> expansions; public Map<String, Script> expansions;
} }

View File

@ -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<Condition> conditions) {
return packId -> {
for (Condition condition : conditions) {
if (!condition.evaluate(packId))
return false;
}
return true;
};
}
@Override
public Set<String> getNames() {
return Set.of("and", "add", "&");
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,8 @@
package io.gitlab.jfronny.respackopts.data.condition;
import java.util.Set;
public interface CollectingConditionFactory {
Condition build(Set<Condition> conditions);
Set<String> getNames();
}

View File

@ -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;
}

View File

@ -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<Condition> 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<String> getNames() {
return Set.of("==", "=", "equal", "eq");
}
}

View File

@ -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<Condition> conditions) {
return packId -> {
for (Condition condition : conditions) {
if (condition.evaluate(packId))
return false;
}
return true;
};
}
@Override
public Set<String> getNames() {
return Set.of("not", "nor", "!");
}
}

View File

@ -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<Condition> conditions) {
return packId -> {
for (Condition condition : conditions) {
if (condition.evaluate(packId))
return true;
}
return false;
};
}
@Override
public Set<String> getNames() {
return Set.of("or", "|");
}
}

View File

@ -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<String, ConfigBranch> 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");
}
}

View File

@ -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<Condition> conditions) {
return packId -> {
boolean bl = false;
for (Condition condition : conditions) {
if (condition.evaluate(packId))
bl = !bl;
}
return bl;
};
}
@Override
public Set<String> getNames() {
return Set.of("^", "xor");
}
}

View File

@ -7,12 +7,11 @@ import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.data.DirRpo; import io.gitlab.jfronny.respackopts.data.DirRpo;
import io.gitlab.jfronny.respackopts.data.PackCapability; import io.gitlab.jfronny.respackopts.data.PackCapability;
import io.gitlab.jfronny.respackopts.util.RpoFormatException; import io.gitlab.jfronny.respackopts.util.RpoFormatException;
import io.gitlab.jfronny.respackopts.filters.conditions.ConditionEvaluator;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import java.io.*; import java.io.*;
public class DirFilterProvider { public class DirFilterEventImpl {
public static void init() { public static void init() {
UserResourceEvents.OPEN.register((type, id, previous, pack) -> { UserResourceEvents.OPEN.register((type, id, previous, pack) -> {
if (!Respackopts.hasCapability(pack, PackCapability.DirFilter)) if (!Respackopts.hasCapability(pack, PackCapability.DirFilter))
@ -33,7 +32,6 @@ public class DirFilterProvider {
if (!Respackopts.hasCapability(pack, PackCapability.DirFilter)) if (!Respackopts.hasCapability(pack, PackCapability.DirFilter))
return previous; return previous;
boolean dirFilterAdditive = Respackopts.hasCapability(pack, PackCapability.DirFilterAdditive); boolean dirFilterAdditive = Respackopts.hasCapability(pack, PackCapability.DirFilterAdditive);
//TODO support files that weren't there at the original location
for (Identifier identifier : previous) { for (Identifier identifier : previous) {
String path = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath(); String path = type.getDirectory() + "/" + identifier.getNamespace() + "/" + identifier.getPath();
DirRpo rpo = findDirRpo(pack, path); DirRpo rpo = findDirRpo(pack, path);
@ -46,7 +44,7 @@ public class DirFilterProvider {
String[] s = path.split("/", 3); String[] s = path.split("/", 3);
if (s.length == 3) { if (s.length == 3) {
ResourcePath rp = new ResourcePath(path); 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)) { for (Identifier resource : pack.findResources(rp.getType(), rp.getId().getNamespace(), rp.getId().getPath(), maxDepth, (a) -> true)) {
String p = type.getDirectory() + "/" + resource.getNamespace() + "/" + resource.getPath(); String p = type.getDirectory() + "/" + resource.getNamespace() + "/" + resource.getPath();
p = p.replace(rpo.fallback, rpo.path + "/"); p = p.replace(rpo.fallback, rpo.path + "/");
@ -86,7 +84,7 @@ public class DirFilterProvider {
if (rpo.conditions == null) if (rpo.conditions == null)
return false; return false;
try { try {
return !ConditionEvaluator.evaluate(rpo.conditions, packId); return !rpo.conditions.evaluate(packId);
} catch (RpoFormatException e) { } catch (RpoFormatException e) {
Respackopts.LOGGER.error("Couldn't parse dir conditions", e); Respackopts.LOGGER.error("Couldn't parse dir conditions", e);
} }

View File

@ -5,9 +5,9 @@ import io.gitlab.jfronny.libjf.data.UserResourceEvents;
import io.gitlab.jfronny.libjf.data.WrappedPack; import io.gitlab.jfronny.libjf.data.WrappedPack;
import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.data.PackCapability; import io.gitlab.jfronny.respackopts.data.PackCapability;
import io.gitlab.jfronny.respackopts.filters.conditions.ResourcePackFilter; import io.gitlab.jfronny.respackopts.filters.util.FileExclusionProvider;
import io.gitlab.jfronny.respackopts.filters.expansion.DataExpander; import io.gitlab.jfronny.respackopts.filters.util.FileExpansionProvider;
import io.gitlab.jfronny.respackopts.filters.fallback.FallbackFilter; import io.gitlab.jfronny.respackopts.filters.util.FileFallbackProvider;
import net.minecraft.resource.AbstractFileResourcePack; import net.minecraft.resource.AbstractFileResourcePack;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -15,7 +15,7 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public class FileFilterProvider { public class FileFilterEventImpl {
public static void init() { public static void init() {
AtomicBoolean containsFileWasFallback = new AtomicBoolean(false); AtomicBoolean containsFileWasFallback = new AtomicBoolean(false);
UserResourceEvents.OPEN.register((type, id, previous, pack) -> { UserResourceEvents.OPEN.register((type, id, previous, pack) -> {
@ -24,8 +24,8 @@ public class FileFilterProvider {
IOException ex = new FileNotFoundException(); IOException ex = new FileNotFoundException();
if (pack.contains(type, id)) { if (pack.contains(type, id)) {
if (containsFileWasFallback.get()) if (containsFileWasFallback.get())
return FallbackFilter.getReplacement(pack, name, ex); return FileFallbackProvider.getReplacement(pack, name, ex);
return DataExpander.replace(previous, pack, name, ex); return FileExpansionProvider.replace(previous, pack, name, ex);
} }
throw ex; throw ex;
}); });
@ -33,9 +33,9 @@ public class FileFilterProvider {
// Warning: the Identifiers here DON'T CONTAIN THE TYPE! // Warning: the Identifiers here DON'T CONTAIN THE TYPE!
// Therefore, it needs to be added when calling a method that generates a ResourcePath! // Therefore, it needs to be added when calling a method that generates a ResourcePath!
if (skip(pack)) return previous; 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 // Completion of the path is handled separately here
FallbackFilter.addFallbackResources(pack, previous, namespace, type); FileFallbackProvider.addFallbackResources(pack, previous, namespace, type);
return previous; return previous;
}); });
UserResourceEvents.CONTAINS.register((type, id, previous, pack) -> { UserResourceEvents.CONTAINS.register((type, id, previous, pack) -> {
@ -43,8 +43,8 @@ public class FileFilterProvider {
containsFileWasFallback.set(false); containsFileWasFallback.set(false);
String name = new ResourcePath(type, id).getName(); String name = new ResourcePath(type, id).getName();
if (previous) { if (previous) {
if (ResourcePackFilter.fileHidden(pack, name)) { if (FileExclusionProvider.fileHidden(pack, name)) {
if (FallbackFilter.fileVisible(pack, name)) { if (FileFallbackProvider.fileVisible(pack, name)) {
containsFileWasFallback.set(true); containsFileWasFallback.set(true);
} else { } else {
return false; return false;
@ -53,7 +53,7 @@ public class FileFilterProvider {
return true; return true;
} }
else { 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); containsFileWasFallback.set(true);
return true; return true;
} }

View File

@ -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<String> getKeys() {
Set<String> strings = new LinkedHashSet<>();
strings.add("add");
strings.add("&");
return strings;
}
}

View File

@ -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<String> getKeys();
}

View File

@ -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<Condition> 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<String, JsonElement> 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<String, ConfigBranch> 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");
}
}

View File

@ -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<Boolean> 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<String> getKeys() {
Set<String> strings = new LinkedHashSet<>();
strings.add("==");
strings.add("=");
strings.add("equal");
strings.add("eq");
return strings;
}
}

View File

@ -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<String> getKeys() {
Set<String> strings = new LinkedHashSet<>();
strings.add("not");
strings.add("nor");
strings.add("!");
return strings;
}
}

View File

@ -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<String> getKeys() {
Set<String> strings = new LinkedHashSet<>();
strings.add("or");
strings.add("|");
return strings;
}
}

View File

@ -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<String> getKeys() {
Set<String> strings = new LinkedHashSet<>();
strings.add("^");
strings.add("xor");
return strings;
}
}

View File

@ -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.ResourcePath;
import io.gitlab.jfronny.libjf.data.WrappedPack; import io.gitlab.jfronny.libjf.data.WrappedPack;
@ -9,7 +9,7 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
public class ResourcePackFilter { public class FileExclusionProvider {
public static boolean fileHidden(WrappedPack pack, String name) { public static boolean fileHidden(WrappedPack pack, String name) {
if (name.endsWith(Respackopts.FILE_EXTENSION)) if (name.endsWith(Respackopts.FILE_EXTENSION))
return false; return false;
@ -26,7 +26,7 @@ public class ResourcePackFilter {
FileRpo rpo = Respackopts.GSON.fromJson(w, FileRpo.class); FileRpo rpo = Respackopts.GSON.fromJson(w, FileRpo.class);
if (rpo.conditions == null) if (rpo.conditions == null)
return false; return false;
return !ConditionEvaluator.evaluate(rpo.conditions, Respackopts.getId(pack)); return !rpo.conditions.evaluate(Respackopts.getId(pack));
} }
catch (Throwable e) { catch (Throwable e) {
Respackopts.LOGGER.error("Could not load RPO file " + name, e); Respackopts.LOGGER.error("Could not load RPO file " + name, e);

View File

@ -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.ResourcePath;
import io.gitlab.jfronny.libjf.data.WrappedPack; import io.gitlab.jfronny.libjf.data.WrappedPack;
@ -9,7 +9,7 @@ import meteordevelopment.starscript.Script;
import java.io.*; import java.io.*;
import java.util.Map; import java.util.Map;
public class DataExpander { public class FileExpansionProvider {
public static synchronized InputStream replace(InputStream is, Map<String, Script> expansions) throws IOException { public static synchronized InputStream replace(InputStream is, Map<String, Script> expansions) throws IOException {
String s = new String(is.readAllBytes()); String s = new String(is.readAllBytes());
for (Map.Entry<String, Script> entry : expansions.entrySet()) { for (Map.Entry<String, Script> entry : expansions.entrySet()) {

View File

@ -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.ResourcePath;
import io.gitlab.jfronny.libjf.data.WrappedPack; import io.gitlab.jfronny.libjf.data.WrappedPack;
@ -14,7 +14,7 @@ import java.io.Reader;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
public class FallbackFilter { public class FileFallbackProvider {
public static boolean fileVisible(WrappedPack pack, String name) { public static boolean fileVisible(WrappedPack pack, String name) {
if (name.endsWith(Respackopts.FILE_EXTENSION)) if (name.endsWith(Respackopts.FILE_EXTENSION))
return false; return false;

View File

@ -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<Condition> {
private static final AndConditionFactory and = new AndConditionFactory();
private static final Set<CollectingConditionFactory> factories = Set.of(
and,
new EqualityConditionFactory(),
new NorConditionFactory(),
new OrConditionFactory(),
new XorConditionFactory()
);
private static final Type conditionSetType = new TypeToken<Set<Condition>>(){}.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<String, JsonElement> 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");
}
}

View File

@ -2,6 +2,7 @@ package io.gitlab.jfronny.respackopts.gson;
import com.google.gson.*; import com.google.gson.*;
import io.gitlab.jfronny.respackopts.data.DirRpo; import io.gitlab.jfronny.respackopts.data.DirRpo;
import io.gitlab.jfronny.respackopts.data.condition.Condition;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
@ -16,18 +17,7 @@ public class DirRpoDeserializer implements JsonDeserializer<DirRpo> {
switch (entry.getKey()) { switch (entry.getKey()) {
case "conditions": case "conditions":
case "condition": case "condition":
if (entry.getValue().isJsonArray()) rpo.conditions = context.deserialize(entry.getValue(), Condition.class);
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");
}
break; break;
case "fallbacks": case "fallbacks":
case "fallback": case "fallback":

View File

@ -3,6 +3,7 @@ package io.gitlab.jfronny.respackopts.gson;
import com.google.gson.*; import com.google.gson.*;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import io.gitlab.jfronny.respackopts.data.FileRpo; import io.gitlab.jfronny.respackopts.data.FileRpo;
import io.gitlab.jfronny.respackopts.data.condition.Condition;
import meteordevelopment.starscript.Script; import meteordevelopment.starscript.Script;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -20,18 +21,7 @@ public class RpoDeserializer implements JsonDeserializer<FileRpo> {
switch (entry.getKey()) { switch (entry.getKey()) {
case "conditions": case "conditions":
case "condition": case "condition":
if (entry.getValue().isJsonArray()) rpo.conditions = context.deserialize(entry.getValue(), Condition.class);
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");
}
break; break;
case "fallbacks": case "fallbacks":
case "fallback": case "fallback":

View File

@ -17,8 +17,8 @@ public class OptionsScreenMixin {
@Inject(at = @At("HEAD"), method = "refreshResourcePacks(Lnet/minecraft/resource/ResourcePackManager;)V") @Inject(at = @At("HEAD"), method = "refreshResourcePacks(Lnet/minecraft/resource/ResourcePackManager;)V")
private void refreshResourcePacks(ResourcePackManager resourcePackManager, CallbackInfo info) { private void refreshResourcePacks(ResourcePackManager resourcePackManager, CallbackInfo info) {
if (Respackopts.forceRespackReload) { if (Respackopts.forcePackReload) {
Respackopts.forceRespackReload = false; Respackopts.forcePackReload = false;
this.settings.resourcePacks.clear(); this.settings.resourcePacks.clear();
} }
} }

View File

@ -1,7 +1,5 @@
package io.gitlab.jfronny.respackopts.mixin; 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.Respackopts;
import io.gitlab.jfronny.respackopts.util.MetadataLocateResult; import io.gitlab.jfronny.respackopts.util.MetadataLocateResult;
import io.gitlab.jfronny.respackopts.data.PackCapability; 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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map; import java.util.Map;
@Mixin(ResourcePackManager.class) @Mixin(ResourcePackManager.class)
@ -32,8 +29,8 @@ public class ResourcePackManagerMixin {
profiles.forEach((s, v) -> { profiles.forEach((s, v) -> {
MetadataLocateResult scan = rpo$locateMetadata(v); MetadataLocateResult scan = rpo$locateMetadata(v);
if (scan.hasMeta()) { if (scan.hasMeta()) {
try { try (InputStream is = scan.pack().open(scan.type(), Respackopts.CONF_ID); InputStreamReader isr = new InputStreamReader(is)) {
PackMeta conf = Respackopts.GSON.fromJson(rpo$readMetadata(scan), PackMeta.class); PackMeta conf = Respackopts.GSON.fromJson(isr, PackMeta.class);
if (Respackopts.META_VERSION < conf.version) { if (Respackopts.META_VERSION < conf.version) {
Respackopts.LOGGER.error(s + " was not loaded as it specifies a newer respackopts version than is installed"); Respackopts.LOGGER.error(s + " was not loaded as it specifies a newer respackopts version than is installed");
return; return;
@ -68,14 +65,4 @@ public class ResourcePackManagerMixin {
return new MetadataLocateResult(pack, false, null); 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();
}
} }

View File

@ -59,7 +59,7 @@ public class GuiFactory {
ConfigEntryBuilder entryBuilder = builder.entryBuilder(); ConfigEntryBuilder entryBuilder = builder.entryBuilder();
builder.setSavingRunnable(() -> { builder.setSavingRunnable(() -> {
Respackopts.save(); Respackopts.save();
Respackopts.forceRespackReload = true; Respackopts.forcePackReload = true;
DashLoaderCompat.forceReload = true; DashLoaderCompat.forceReload = true;
Respackopts.reloadData(); Respackopts.reloadData();
}); });

View File

@ -4,4 +4,8 @@ public class RpoFormatException extends Exception {
public RpoFormatException(String message) { public RpoFormatException(String message) {
super(message); super(message);
} }
public RpoFormatException(String message, Throwable cause) {
super(message, cause);
}
} }