Proper conditions
This commit is contained in:
parent
b07e0a0671
commit
f825b73e38
@ -46,6 +46,7 @@ There have been issues with LibCD in development, so it might be smart not to us
|
||||
Respackopts allows creating conditional resources by creating a file named `{targetFile}.rpo`.\
|
||||
This file is a json file that contains an array named "conditions". The resource will be ignored if any of the conditions are not met.\
|
||||
This allows (for example) overrides for textures to only be loaded if the user enables them through the config.\
|
||||
It also allows the following operations: `and`, `equal`, `nor`/`not`, `or`, `xor`
|
||||
As an example can be seen [here](https://gitlab.com/JFronny/respackopts/-/tree/master/run/resourcepacks/lumi/assets/minecraft/lang)
|
||||
## Mod developers
|
||||
All data is available in static HashMaps in `io.gitlab.jfronny.respackopts.Respackopts`.\
|
||||
|
@ -1,5 +1,10 @@
|
||||
{
|
||||
"conditions": [
|
||||
"lumi:subcategoryTest.enableLang"
|
||||
"lumi:subcategoryTest.enableLang",
|
||||
{
|
||||
"not": [
|
||||
"lumi:subcategoryTest.enableLangForceDisable"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"default": 16,
|
||||
"max": 20
|
||||
},
|
||||
"enableLang": true
|
||||
"enableLang": true,
|
||||
"enableLangForceDisable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,27 +134,4 @@ public class Respackopts implements ClientModInitializer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean matchStringCondition(String condition) throws SyntaxError {
|
||||
if (condition == null) {
|
||||
throw new SyntaxError("Condition must not be null");
|
||||
}
|
||||
if (!condition.contains(":")) {
|
||||
throw new SyntaxError("You must include you resource pack ID in conditions (format: pack:some.key)");
|
||||
}
|
||||
AtomicBoolean found = new AtomicBoolean(false);
|
||||
AtomicBoolean output = new AtomicBoolean(false);
|
||||
Respackopts.resPackMetas.forEach((r, v) -> {
|
||||
String sourcePack = condition.split(":")[0];
|
||||
String name = condition.substring(condition.indexOf(':') + 1);
|
||||
if (Objects.equals(v.id, sourcePack)) {
|
||||
found.set(true);
|
||||
output.set(Respackopts.boolVals.get(sourcePack).get(name));
|
||||
}
|
||||
});
|
||||
if (!found.get()) {
|
||||
throw new SyntaxError("Could not find pack with specified ID");
|
||||
}
|
||||
return output.get();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package io.gitlab.jfronny.respackopts.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class AndCondition implements Condition {
|
||||
@Override
|
||||
public boolean evaluate(JsonElement node) throws SyntaxError {
|
||||
if (!node.isJsonArray())
|
||||
throw new SyntaxError("\"and\" condition requires an array of conditions");
|
||||
for (JsonElement jsonElement : node.getAsJsonArray()) {
|
||||
if (!ConditionEvaluator.evaluate(jsonElement))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> strings = new LinkedHashSet<>();
|
||||
strings.add("add");
|
||||
strings.add("&");
|
||||
strings.add("conditions"); // This is also the root condition
|
||||
return strings;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package io.gitlab.jfronny.respackopts.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface Condition {
|
||||
boolean evaluate(JsonElement node) throws SyntaxError;
|
||||
Set<String> getKeys();
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package io.gitlab.jfronny.respackopts.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import io.gitlab.jfronny.respackopts.Respackopts;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ConditionEvaluator {
|
||||
private static 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) throws SyntaxError {
|
||||
if (condition.isJsonPrimitive() && condition.getAsJsonPrimitive().isString())
|
||||
return evaluate(condition.getAsString());
|
||||
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());
|
||||
}
|
||||
}
|
||||
throw new SyntaxError("Could not find condition: " + entry.getKey());
|
||||
}
|
||||
}
|
||||
throw new SyntaxError("Condition entries may only be json objects containing one key and one value or strings");
|
||||
}
|
||||
|
||||
public static boolean evaluate(String condition) throws SyntaxError {
|
||||
if (condition == null) {
|
||||
throw new SyntaxError("Condition must not be null");
|
||||
}
|
||||
if (!condition.contains(":")) {
|
||||
throw new SyntaxError("You must include you resource pack ID in conditions (format: pack:some.key)");
|
||||
}
|
||||
AtomicBoolean found = new AtomicBoolean(false);
|
||||
AtomicBoolean output = new AtomicBoolean(false);
|
||||
Respackopts.resPackMetas.forEach((r, v) -> {
|
||||
String sourcePack = condition.split(":")[0];
|
||||
String name = condition.substring(condition.indexOf(':') + 1);
|
||||
if (Objects.equals(v.id, sourcePack)) {
|
||||
found.set(true);
|
||||
output.set(Respackopts.boolVals.get(sourcePack).get(name));
|
||||
}
|
||||
});
|
||||
if (!found.get()) {
|
||||
throw new SyntaxError("Could not find pack with specified ID");
|
||||
}
|
||||
return output.get();
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package io.gitlab.jfronny.respackopts.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
//TODO implement equality checking for string/number variables
|
||||
public class EqualityCondition implements Condition {
|
||||
@Override
|
||||
public boolean evaluate(JsonElement node) throws SyntaxError {
|
||||
if (!node.isJsonArray())
|
||||
throw new SyntaxError("\"equal\" condition requires an array of conditions");
|
||||
Optional<Boolean> v = Optional.empty();
|
||||
for (JsonElement jsonElement : node.getAsJsonArray()) {
|
||||
boolean current = ConditionEvaluator.evaluate(jsonElement);
|
||||
if (!v.isPresent())
|
||||
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;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package io.gitlab.jfronny.respackopts.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class NorCondition implements Condition {
|
||||
@Override
|
||||
public boolean evaluate(JsonElement node) throws SyntaxError {
|
||||
if (!node.isJsonArray())
|
||||
throw new SyntaxError("\"not\"/\"nor\" condition requires an array of conditions");
|
||||
for (JsonElement jsonElement : node.getAsJsonArray()) {
|
||||
if (ConditionEvaluator.evaluate(jsonElement))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> strings = new LinkedHashSet<>();
|
||||
strings.add("not");
|
||||
strings.add("nor");
|
||||
strings.add("!");
|
||||
return strings;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package io.gitlab.jfronny.respackopts.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class OrCondition implements Condition {
|
||||
@Override
|
||||
public boolean evaluate(JsonElement node) throws SyntaxError {
|
||||
if (!node.isJsonArray())
|
||||
throw new SyntaxError("\"or\" condition requires an array of conditions");
|
||||
for (JsonElement jsonElement : node.getAsJsonArray()) {
|
||||
if (ConditionEvaluator.evaluate(jsonElement))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> strings = new LinkedHashSet<>();
|
||||
strings.add("or");
|
||||
strings.add("|");
|
||||
return strings;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package io.gitlab.jfronny.respackopts.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import io.gitlab.jfronny.respackopts.Respackopts;
|
||||
import io.gitlab.jfronny.respackopts.data.RpoResourceEntry;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@ -23,18 +23,7 @@ public class ResourcePackFilter {
|
||||
if (!containsFileBase.test(name + Respackopts.fileExtension))
|
||||
return true;
|
||||
try (InputStream stream = openFileBase.apply(name + Respackopts.fileExtension); Reader w = new InputStreamReader(stream)) {
|
||||
RpoResourceEntry entry = Respackopts.g.fromJson(w, RpoResourceEntry.class);
|
||||
if (entry.conditions != null) {
|
||||
for (String condition : entry.conditions) {
|
||||
if (!Respackopts.matchStringCondition(condition))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Respackopts.logger.error("Conditions null for " + name);
|
||||
return true;
|
||||
}
|
||||
return ConditionEvaluator.evaluate(Respackopts.g.fromJson(w, JsonElement.class));
|
||||
}
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
|
@ -0,0 +1,28 @@
|
||||
package io.gitlab.jfronny.respackopts.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class XorCondition implements Condition {
|
||||
@Override
|
||||
public boolean evaluate(JsonElement node) throws SyntaxError {
|
||||
if (!node.isJsonArray())
|
||||
throw new SyntaxError("\"xor\" condition requires an array of conditions");
|
||||
boolean bl = false;
|
||||
for (JsonElement jsonElement : node.getAsJsonArray()) {
|
||||
if (ConditionEvaluator.evaluate(jsonElement))
|
||||
bl = !bl;
|
||||
}
|
||||
return bl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> strings = new LinkedHashSet<>();
|
||||
strings.add("^");
|
||||
strings.add("xor");
|
||||
return strings;
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package io.gitlab.jfronny.respackopts.data;
|
||||
|
||||
public class RpoResourceEntry {
|
||||
public String[] conditions;
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package io.gitlab.jfronny.respackopts.integration;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import io.github.cottonmc.libcd.api.CDSyntaxError;
|
||||
import io.github.cottonmc.libcd.api.condition.ConditionManager;
|
||||
import io.github.cottonmc.libcd.api.init.ConditionInitializer;
|
||||
import io.gitlab.jfronny.respackopts.Respackopts;
|
||||
import io.gitlab.jfronny.respackopts.conditions.ConditionEvaluator;
|
||||
import io.gitlab.jfronny.respackopts.conditions.SyntaxError;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
@ -11,15 +13,22 @@ public class LibCDCompat implements ConditionInitializer {
|
||||
@Override
|
||||
public void initConditions(ConditionManager conditionManager) {
|
||||
conditionManager.registerCondition(new Identifier(Respackopts.ID, "cfg"), q -> {
|
||||
if (!(q instanceof String)) {
|
||||
throw new CDSyntaxError("Expected string");
|
||||
if (q instanceof String) {
|
||||
try {
|
||||
return ConditionEvaluator.evaluate((String) q);
|
||||
} catch (Throwable error) {
|
||||
throw new CDSyntaxError(error.getMessage());
|
||||
}
|
||||
}
|
||||
String s = (String) q;
|
||||
try {
|
||||
return Respackopts.matchStringCondition(s);
|
||||
} catch (SyntaxError syntaxError) {
|
||||
throw new CDSyntaxError(syntaxError.getMessage());
|
||||
else if (q instanceof JsonElement) {
|
||||
try {
|
||||
return ConditionEvaluator.evaluate((JsonElement) q);
|
||||
} catch (Throwable error) {
|
||||
throw new CDSyntaxError(error.getMessage());
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new CDSyntaxError("Expected Json element or string for rpo libcd conditions");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user