1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
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.cit.CITParsingException;
import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup;
import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue;
import static java.lang.Integer.*;
/**
* Common condition parser for integers with optional support for ranges, negatives and percentages.
*/
public abstract class IntegerCondition extends CITCondition {
/**
* Whether this condition should accept given ranges/negatives/percentages.
*/
protected final boolean supportsRanges, supportsNegatives, supportsPercentages;
/**
* If ranges are accepted, parsed minimum/maximum integers. If not, minimum is the parsed value.
*/
protected int min, max;
/**
* Whether the parsed value is a range/percentage.
*/
protected boolean range = false, percentage = false;
protected IntegerCondition(boolean supportsRanges, boolean supportsNegatives, boolean supportsPercentages) {
this.supportsRanges = supportsRanges;
this.supportsNegatives = supportsNegatives;
this.supportsPercentages = supportsPercentages;
}
/**
* Converts the given context to an integer to compare the parsed value to.
* @param context context to retrieve the compared value from
* @return the integer value associated with the given context
*/
protected int getValue(CITContext context) {
throw new AssertionError("Not implemented by this condition");
}
/**
* Converts the given context to a max integer to be used when percentages are enabled.
* @param context context to retrieve the max value from
* @return the max integer value associated with the given context
*/
protected int getPercentageTotalValue(CITContext context) {
throw new AssertionError("Not implemented by this condition");
}
@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 == min;
}
}
|