diff options
Diffstat (limited to 'src')
8 files changed, 493 insertions, 17 deletions
diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/cit/CITCondition.java b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/CITCondition.java index 7640d3c..03f118f 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/cit/CITCondition.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/CITCondition.java @@ -24,12 +24,4 @@ public abstract class CITCondition { protected void warn(String message, PropertyValue value, PropertyGroup properties) { CITResewn.logWarnLoading("Warning: " + CITParsingException.descriptionOf(message, properties, value.position())); } - - protected int parseInteger(PropertyValue value, PropertyGroup properties) throws CITParsingException { - try { - return Integer.parseInt(value.value()); - } catch (NumberFormatException e) { - throw new CITParsingException("\"" + value.value() + "\" is not a valid integer", properties, value.position()); - } - } } diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/DoubleCondition.java b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/DoubleCondition.java new file mode 100644 index 0000000..60b6e1a --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/DoubleCondition.java @@ -0,0 +1,132 @@ +package shcm.shsupercm.fabric.citresewn.cit.builtin.conditions; + +import shcm.shsupercm.fabric.citresewn.cit.CITCondition; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.ex.CITParsingException; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue; + +import static java.lang.Double.*; + +public abstract class DoubleCondition extends CITCondition { + protected final boolean supportsRanges, supportsNegatives, supportsPercentages; + + protected double min, max; + protected boolean range = false, percentage = false; + + protected DoubleCondition(boolean supportsRanges, boolean supportsNegatives, boolean supportsPercentages) { + this.supportsRanges = supportsRanges; + this.supportsNegatives = supportsNegatives; + this.supportsPercentages = supportsPercentages; + } + + protected abstract double getValue(CITContext context); + + protected double getPercentageTotalValue(CITContext context) { + return 0; + } + + @Override + public void load(PropertyValue value, PropertyGroup properties) throws CITParsingException { + String strValue = value.value(); + if (supportsPercentages && (percentage = strValue.contains("%"))) + strValue = strValue.replace("%", ""); + + try { + if (range = supportsRanges) { + if (supportsNegatives) { + switch (strValue.length() - strValue.replace("-", "").length()) { // dashesCount + case 0 -> { + range = false; + min = parseDouble(strValue); + } + case 1 -> { + if (strValue.startsWith("-")) { + range = false; + min = parseDouble(strValue); + } else if (strValue.endsWith("-")) { + min = parseDouble(strValue.substring(0, strValue.length() - 1)); + max = MAX_VALUE; + } else { + String[] split = strValue.split("-"); + min = parseDouble(split[0]); + max = parseDouble(split[1]); + } + } + case 2 -> { + if (strValue.startsWith("--")) { + min = MIN_VALUE; + max = parseDouble(strValue.substring(1)); + } else if (strValue.startsWith("-") && strValue.endsWith("-")) { + min = parseDouble(strValue.substring(0, strValue.length() - 1)); + max = MAX_VALUE; + } else if (strValue.startsWith("-") && !strValue.endsWith("-") && !strValue.contains("--")) { + int lastDash = strValue.lastIndexOf('-'); + min = parseDouble(strValue.substring(0, lastDash)); + max = parseDouble(strValue.substring(lastDash + 1)); + } else + throw new CITParsingException("Could not parse range", properties, value.position()); + } + case 3 -> { + if (!strValue.contains("---") && strValue.startsWith("-")) { + String[] split = strValue.split("--"); + if (split.length != 2 || split[0].isEmpty() || split[1].isEmpty()) + throw new CITParsingException("Could not parse range", properties, value.position()); + + min = parseDouble(split[0]); + max = -parseDouble(split[1]); + } else + throw new CITParsingException("Could not parse range", properties, value.position()); + } + + default -> throw new CITParsingException("Could not parse range", properties, value.position()); + } + } else { + if (range = strValue.contains("-")) { + if (strValue.contains("--")) + throw new CITParsingException("Could not parse range", properties, value.position()); + String[] split = strValue.split("-"); + switch (split.length) { + case 1 -> { + min = parseDouble(split[0]); + max = MAX_VALUE; + } + case 2 -> { + if (strValue.endsWith("-")) + throw new CITParsingException("Could not parse range", properties, value.position()); + min = split[0].isEmpty() ? MIN_VALUE : parseDouble(split[0]); + max = split[1].isEmpty() ? MAX_VALUE : parseDouble(split[1]); + } + default -> throw new CITParsingException("Could not parse range", properties, value.position()); + } + } else + min = parseDouble(strValue); + } + } else { + min = parseDouble(strValue); + if (!supportsNegatives && min < 0) + throw new CITParsingException("Negatives are not allowed", properties, value.position()); + } + + if (range) { + if (min == max) + range = false; + else if (min > max) + throw new CITParsingException("Could not parse range", properties, value.position()); + } + } catch (Exception e) { + throw e instanceof CITParsingException citE ? citE : new CITParsingException("Could not parse double", properties, value.position(), e); + } + } + + @Override + public boolean test(CITContext context) { + double value = getValue(context); + + if (percentage) { + double percentValue = 100d * value / getPercentageTotalValue(context); + return range ? min <= percentValue && percentValue <= max : percentValue == min; + } else + return range ? min <= value && value <= max : value == min; + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/FloatCondition.java b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/FloatCondition.java new file mode 100644 index 0000000..24de921 --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/FloatCondition.java @@ -0,0 +1,132 @@ +package shcm.shsupercm.fabric.citresewn.cit.builtin.conditions; + +import shcm.shsupercm.fabric.citresewn.cit.CITCondition; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.ex.CITParsingException; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue; + +import static java.lang.Float.*; + +public abstract class FloatCondition extends CITCondition { + protected final boolean supportsRanges, supportsNegatives, supportsPercentages; + + protected float min, max; + protected boolean range = false, percentage = false; + + protected FloatCondition(boolean supportsRanges, boolean supportsNegatives, boolean supportsPercentages) { + this.supportsRanges = supportsRanges; + this.supportsNegatives = supportsNegatives; + this.supportsPercentages = supportsPercentages; + } + + protected abstract float getValue(CITContext context); + + protected float getPercentageTotalValue(CITContext context) { + return 0; + } + + @Override + public void load(PropertyValue value, PropertyGroup properties) throws CITParsingException { + String strValue = value.value(); + if (supportsPercentages && (percentage = strValue.contains("%"))) + strValue = strValue.replace("%", ""); + + try { + if (range = supportsRanges) { + if (supportsNegatives) { + switch (strValue.length() - strValue.replace("-", "").length()) { // dashesCount + case 0 -> { + range = false; + min = parseFloat(strValue); + } + case 1 -> { + if (strValue.startsWith("-")) { + range = false; + min = parseFloat(strValue); + } else if (strValue.endsWith("-")) { + min = parseFloat(strValue.substring(0, strValue.length() - 1)); + max = MAX_VALUE; + } else { + String[] split = strValue.split("-"); + min = parseFloat(split[0]); + max = parseFloat(split[1]); + } + } + case 2 -> { + if (strValue.startsWith("--")) { + min = MIN_VALUE; + max = parseFloat(strValue.substring(1)); + } else if (strValue.startsWith("-") && strValue.endsWith("-")) { + min = parseFloat(strValue.substring(0, strValue.length() - 1)); + max = MAX_VALUE; + } else if (strValue.startsWith("-") && !strValue.endsWith("-") && !strValue.contains("--")) { + int lastDash = strValue.lastIndexOf('-'); + min = parseFloat(strValue.substring(0, lastDash)); + max = parseFloat(strValue.substring(lastDash + 1)); + } else + throw new CITParsingException("Could not parse range", properties, value.position()); + } + case 3 -> { + if (!strValue.contains("---") && strValue.startsWith("-")) { + String[] split = strValue.split("--"); + if (split.length != 2 || split[0].isEmpty() || split[1].isEmpty()) + throw new CITParsingException("Could not parse range", properties, value.position()); + + min = parseFloat(split[0]); + max = -parseFloat(split[1]); + } else + throw new CITParsingException("Could not parse range", properties, value.position()); + } + + default -> throw new CITParsingException("Could not parse range", properties, value.position()); + } + } else { + if (range = strValue.contains("-")) { + if (strValue.contains("--")) + throw new CITParsingException("Could not parse range", properties, value.position()); + String[] split = strValue.split("-"); + switch (split.length) { + case 1 -> { + min = parseFloat(split[0]); + max = MAX_VALUE; + } + case 2 -> { + if (strValue.endsWith("-")) + throw new CITParsingException("Could not parse range", properties, value.position()); + min = split[0].isEmpty() ? MIN_VALUE : parseFloat(split[0]); + max = split[1].isEmpty() ? MAX_VALUE : parseFloat(split[1]); + } + default -> throw new CITParsingException("Could not parse range", properties, value.position()); + } + } else + min = parseFloat(strValue); + } + } else { + min = parseFloat(strValue); + if (!supportsNegatives && min < 0) + throw new CITParsingException("Negatives are not allowed", properties, value.position()); + } + + if (range) { + if (min == max) + range = false; + else if (min > max) + throw new CITParsingException("Could not parse range", properties, value.position()); + } + } catch (Exception e) { + throw e instanceof CITParsingException citE ? citE : new CITParsingException("Could not parse float", properties, value.position(), e); + } + } + + @Override + public boolean test(CITContext context) { + float value = getValue(context); + + if (percentage) { + float percentValue = 100f * value / getPercentageTotalValue(context); + return range ? min <= percentValue && percentValue <= max : percentValue == min; + } else + return range ? min <= value && value <= max : value == min; + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/IntegerCondition.java b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/IntegerCondition.java new file mode 100644 index 0000000..6701338 --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/IntegerCondition.java @@ -0,0 +1,132 @@ +package shcm.shsupercm.fabric.citresewn.cit.builtin.conditions; + +import shcm.shsupercm.fabric.citresewn.cit.CITCondition; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.ex.CITParsingException; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue; + +import static java.lang.Integer.*; + +public abstract class IntegerCondition extends CITCondition { + protected final boolean supportsRanges, supportsNegatives, supportsPercentages; + + protected int min, max; + protected boolean range = false, percentage = false; + + protected IntegerCondition(boolean supportsRanges, boolean supportsNegatives, boolean supportsPercentages) { + this.supportsRanges = supportsRanges; + this.supportsNegatives = supportsNegatives; + this.supportsPercentages = supportsPercentages; + } + + protected abstract int getValue(CITContext context); + + protected int getPercentageTotalValue(CITContext context) { + return 0; + } + + @Override + public void load(PropertyValue value, PropertyGroup properties) throws CITParsingException { + String strValue = value.value(); + if (supportsPercentages && (percentage = strValue.contains("%"))) + strValue = strValue.replace("%", ""); + + try { + if (range = supportsRanges) { + if (supportsNegatives) { + switch (strValue.length() - strValue.replace("-", "").length()) { // dashesCount + case 0 -> { + range = false; + min = parseInt(strValue); + } + case 1 -> { + if (strValue.startsWith("-")) { + range = false; + min = parseInt(strValue); + } else if (strValue.endsWith("-")) { + min = parseInt(strValue.substring(0, strValue.length() - 1)); + max = MAX_VALUE; + } else { + String[] split = strValue.split("-"); + min = parseInt(split[0]); + max = parseInt(split[1]); + } + } + case 2 -> { + if (strValue.startsWith("--")) { + min = MIN_VALUE; + max = parseInt(strValue.substring(1)); + } else if (strValue.startsWith("-") && strValue.endsWith("-")) { + min = parseInt(strValue.substring(0, strValue.length() - 1)); + max = MAX_VALUE; + } else if (strValue.startsWith("-") && !strValue.endsWith("-") && !strValue.contains("--")) { + int lastDash = strValue.lastIndexOf('-'); + min = parseInt(strValue.substring(0, lastDash)); + max = parseInt(strValue.substring(lastDash + 1)); + } else + throw new CITParsingException("Could not parse range", properties, value.position()); + } + case 3 -> { + if (!strValue.contains("---") && strValue.startsWith("-")) { + String[] split = strValue.split("--"); + if (split.length != 2 || split[0].isEmpty() || split[1].isEmpty()) + throw new CITParsingException("Could not parse range", properties, value.position()); + + min = parseInt(split[0]); + max = -parseInt(split[1]); + } else + throw new CITParsingException("Could not parse range", properties, value.position()); + } + + default -> throw new CITParsingException("Could not parse range", properties, value.position()); + } + } else { + if (range = strValue.contains("-")) { + if (strValue.contains("--")) + throw new CITParsingException("Could not parse range", properties, value.position()); + String[] split = strValue.split("-"); + switch (split.length) { + case 1 -> { + min = parseInt(split[0]); + max = MAX_VALUE; + } + case 2 -> { + if (strValue.endsWith("-")) + throw new CITParsingException("Could not parse range", properties, value.position()); + min = split[0].isEmpty() ? MIN_VALUE : parseInt(split[0]); + max = split[1].isEmpty() ? MAX_VALUE : parseInt(split[1]); + } + default -> throw new CITParsingException("Could not parse range", properties, value.position()); + } + } else + min = parseInt(strValue); + } + } else { + min = parseInt(strValue); + if (!supportsNegatives && min < 0) + throw new CITParsingException("Negatives are not allowed", properties, value.position()); + } + + if (range) { + if (min == max) + range = false; + else if (min > max) + throw new CITParsingException("Could not parse range", properties, value.position()); + } + } catch (Exception e) { + throw e instanceof CITParsingException citE ? citE : new CITParsingException("Could not parse integer", properties, value.position(), e); + } + } + + @Override + public boolean test(CITContext context) { + int value = getValue(context); + + if (percentage) { + double percentValue = 100d * (double) value / (double) getPercentageTotalValue(context); + return range ? min <= percentValue && percentValue <= max : percentValue == (double) min; + } else + return range ? min <= value && value <= max : value == (double) min; + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/ListCondition.java b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/ListCondition.java new file mode 100644 index 0000000..151119b --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/ListCondition.java @@ -0,0 +1,79 @@ +package shcm.shsupercm.fabric.citresewn.cit.builtin.conditions; + +import shcm.shsupercm.fabric.citresewn.cit.CITCondition; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.ex.CITParsingException; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; +import java.util.regex.Pattern; + +public abstract class ListCondition<T extends CITCondition> extends CITCondition { + private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\p{Zs}+"); + + private final Class<T> conditionType; + protected final Type listType; + protected final Pattern delimiter; + protected final Supplier<T> conditionSupplier; + + protected T[] conditions; + + protected ListCondition(Class<T> conditionType, Type listType, Pattern delimiter, Supplier<T> conditionSupplier) { + this.conditionType = conditionType; + this.listType = listType; + this.delimiter = delimiter; + this.conditionSupplier = conditionSupplier; + } + + protected ListCondition(Class<T> conditionType, Supplier<T> conditionSupplier) { + this(conditionType, Type.OR, PATTERN_WHITESPACE, conditionSupplier); + } + + @Override + public void load(PropertyValue value, PropertyGroup properties) throws CITParsingException { + List<T> conditions = new ArrayList<>(); + + for (String conditionValue : delimiter.split(value.value())) { + T condition = conditionSupplier.get(); + condition.load(new PropertyValue(value.keyMetadata(), conditionValue, value.delimiter(), value.position(), value.propertiesIdentifier(), value.packName()), properties); + conditions.add(condition); + } + + //noinspection unchecked + this.conditions = conditions.toArray((T[]) Array.newInstance(conditionType, 0)); + } + + @Override + public boolean test(CITContext context) { + return listType.test(conditions, context); + } + + public enum Type { + OR { + @Override + public boolean test(CITCondition[] conditions, CITContext context) { + for (CITCondition condition : conditions) + if (condition.test(context)) + return true; + + return false; + } + }, + AND { + @Override + public boolean test(CITCondition[] conditions, CITContext context) { + for (CITCondition condition : conditions) + if (!condition.test(context)) + return false; + + return true; + } + }; + + public abstract boolean test(CITCondition[] conditions, CITContext context); + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/WeightCondition.java b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/WeightCondition.java index 54f26ff..6ad3783 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/WeightCondition.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/cit/builtin/conditions/WeightCondition.java @@ -8,20 +8,25 @@ import shcm.shsupercm.fabric.citresewn.cit.CITContext; import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup; import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue; -public class WeightCondition extends CITCondition { +public class WeightCondition extends IntegerCondition { @Entrypoint(CITConditionContainer.ENTRYPOINT) public static final CITConditionContainer<WeightCondition> CONTAINER = new CITConditionContainer<>(WeightCondition.class, WeightCondition::new, "weight"); - public int weight = 0; + public WeightCondition() { + super(false, true, false); + } - @Override - public void load(PropertyValue value, PropertyGroup properties) throws CITParsingException { - this.weight = parseInteger(value, properties); + public int getWeight() { + return this.min; + } + + public void setWeight(int weight) { + this.min = weight; } @Override - public boolean test(CITContext context) { - return true; + protected int getValue(CITContext context) { + return 0; } } diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/ex/CITParsingException.java b/src/main/java/shcm/shsupercm/fabric/citresewn/ex/CITParsingException.java index b3e126f..811d16b 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/ex/CITParsingException.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/ex/CITParsingException.java @@ -3,6 +3,10 @@ package shcm.shsupercm.fabric.citresewn.ex; import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup; public class CITParsingException extends Exception { + public CITParsingException(String message, PropertyGroup propertyGroup, int position, Throwable throwable) { + super("Errored while parsing CIT: " + descriptionOf(message, propertyGroup, position), throwable); + } + public CITParsingException(String message, PropertyGroup propertyGroup, int position) { super("Errored while parsing CIT: " + descriptionOf(message, propertyGroup, position)); } diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/PackParser.java b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/PackParser.java index 5096543..5f5a5c9 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/PackParser.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/PackParser.java @@ -106,7 +106,7 @@ public class PackParser { conditions.removeIf(condition -> { if (condition instanceof WeightCondition weightCondition) { - weight.weight = weightCondition.weight; + weight.setWeight(weightCondition.getWeight()); return true; } @@ -115,6 +115,6 @@ public class PackParser { citType.load(conditions, properties, resourceManager); - return new CIT<>(properties.identifier, properties.packName, citType, conditions.toArray(new CITCondition[0]), weight.weight); + return new CIT<>(properties.identifier, properties.packName, citType, conditions.toArray(new CITCondition[0]), weight.getWeight()); } } |