aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/shcm/shsupercm/fabric/citresewn
diff options
context:
space:
mode:
authorSHsuperCM <shsupercm@gmail.com>2021-08-21 10:57:40 +0300
committerSHsuperCM <shsupercm@gmail.com>2021-08-21 10:57:40 +0300
commit9d5a632898e886ba0081e189dc88c9ffbaaa8e3b (patch)
tree4012903d4fe3515a6771828d90266900b35f136d /src/main/java/shcm/shsupercm/fabric/citresewn
parent676c5fafb20591f3f3a61843b87d75372f77c120 (diff)
downloadCITResewn-9d5a632898e886ba0081e189dc88c9ffbaaa8e3b.tar.gz
CITResewn-9d5a632898e886ba0081e189dc88c9ffbaaa8e3b.tar.bz2
CITResewn-9d5a632898e886ba0081e189dc88c9ffbaaa8e3b.zip
Parse nbt
Diffstat (limited to 'src/main/java/shcm/shsupercm/fabric/citresewn')
-rw-r--r--src/main/java/shcm/shsupercm/fabric/citresewn/mixin/NbtCompoundAccessor.java14
-rw-r--r--src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java109
2 files changed, 123 insertions, 0 deletions
diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/NbtCompoundAccessor.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/NbtCompoundAccessor.java
new file mode 100644
index 0000000..2264638
--- /dev/null
+++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/NbtCompoundAccessor.java
@@ -0,0 +1,14 @@
+package shcm.shsupercm.fabric.citresewn.mixin;
+
+import net.minecraft.nbt.NbtCompound;
+import net.minecraft.nbt.NbtElement;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.Map;
+
+@Mixin(NbtCompound.class)
+public interface NbtCompoundAccessor {
+ @Accessor
+ Map<String, NbtElement> getEntries();
+}
diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java
index 564462c..58716c1 100644
--- a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java
+++ b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java
@@ -2,15 +2,20 @@ package shcm.shsupercm.fabric.citresewn.pack.cits;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.item.Item;
+import net.minecraft.nbt.*;
import net.minecraft.resource.ResourceType;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import net.minecraft.util.registry.Registry;
+import org.apache.commons.lang3.StringEscapeUtils;
import shcm.shsupercm.fabric.citresewn.ex.CITParseException;
+import shcm.shsupercm.fabric.citresewn.mixin.NbtCompoundAccessor;
import shcm.shsupercm.fabric.citresewn.pack.CITPack;
import java.util.*;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
public abstract class CIT {
public final Set<Item> items = new HashSet<>();
@@ -31,6 +36,8 @@ public abstract class CIT {
public final Hand hand;
+ public final Predicate<NbtCompound> nbt;
+
public CIT(CITPack pack, Identifier identifier, Properties properties) throws CITParseException {
try {
for (String itemId : (properties.getProperty("items", properties.getProperty("matchItems", " "))).split(" "))
@@ -167,8 +174,110 @@ public abstract class CIT {
case "off" -> Hand.OFF_HAND;
default -> null;
};
+
+ List<Predicate<NbtCompound>> nbtPredicates = new ArrayList<>();
+ for (Object o : properties.keySet())
+ if (o instanceof String property && property.startsWith("nbt.")) {
+ final String[] path = property.substring(4).split("\\.");
+ final Predicate<String> match;
+
+ String matchProperty = StringEscapeUtils.unescapeJava(properties.getProperty(property));
+ final boolean caseSensitive = !matchProperty.startsWith("i");
+ if (matchProperty.startsWith(caseSensitive ? "pattern:" : "ipattern:")) {
+ final String pattern = caseSensitive ? matchProperty.substring(8) : matchProperty.substring(9).toLowerCase(Locale.ENGLISH);
+ match = s -> matchesPattern(caseSensitive ? s : s.toLowerCase(), pattern, 0, s.length(), 0, pattern.length());
+ } else if (matchProperty.startsWith(caseSensitive ? "regex:" : "iregex:")) {
+ final Pattern pattern = Pattern.compile(caseSensitive ? matchProperty.substring(5) : matchProperty.substring(6).toLowerCase(Locale.ENGLISH));
+ match = s -> pattern.matcher(caseSensitive ? s : s.toLowerCase()).matches();
+ } else
+ match = s -> s.equals(matchProperty);
+
+ nbtPredicates.add(new Predicate<NbtCompound>() {
+ public boolean test(NbtElement nbtElement, int index) {
+ if (index >= path.length) {
+ if (nbtElement instanceof NbtString nbtString) {
+ return match.test(nbtString.asString());
+ } else if (nbtElement instanceof AbstractNbtNumber nbtNumber)
+ return match.test(String.valueOf(nbtNumber.numberValue()));
+ } else {
+ String name = path[index];
+ if (name.equals("*")) {
+ if (nbtElement instanceof NbtCompound nbtCompound) {
+ for (NbtElement subElement : ((NbtCompoundAccessor) nbtCompound).getEntries().values())
+ if (test(subElement, index + 1))
+ return true;
+ } else if (nbtElement instanceof NbtList nbtList) {
+ for (NbtElement subElement : nbtList)
+ if (test(subElement, index + 1))
+ return true;
+ }
+ } else {
+ if (nbtElement instanceof NbtCompound nbtCompound) {
+ NbtElement subElement = nbtCompound.get(name);
+ return subElement != null && test(subElement, index + 1);
+ } else if (nbtElement instanceof NbtList nbtList) {
+ try {
+ NbtElement subElement = nbtList.get(Integer.parseInt(name));
+ return subElement != null && test(subElement, index + 1);
+ } catch (NumberFormatException ignored) {
+ return false;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean test(NbtCompound nbtCompound) {
+ return test(nbtCompound, 0);
+ }
+ });
+ }
+ this.nbt = nbtCompound -> {
+ for (Predicate<NbtCompound> predicate : nbtPredicates)
+ if(!predicate.test(nbtCompound))
+ return false;
+ return true;
+ };
+
} catch (Exception e) {
throw new CITParseException(pack.resourcePack, identifier, e.getMessage());
}
}
+
+ /**
+ * Author: Paul "prupe" Rupe<br>
+ * Taken from MCPatcher under public domain licensing.<br>
+ * https://bitbucket.org/prupe/mcpatcher/src/1aa45839b2cd029143809edfa60ec59e5ef75f80/newcode/src/com/prupe/mcpatcher/mal/nbt/NBTRule.java#lines-269:301
+ */
+ public static boolean matchesPattern(String value, String pattern, int curV, int maxV, int curG, int maxG) {
+ for (; curG < maxG; curG++, curV++) {
+ char g = pattern.charAt(curG);
+ if (g == '*') {
+ while (true) {
+ if (matchesPattern(value, pattern, curV, maxV, curG + 1, maxG)) {
+ return true;
+ }
+ if (curV >= maxV) {
+ break;
+ }
+ curV++;
+ }
+ return false;
+ } else if (curV >= maxV) {
+ break;
+ } else if (g == '?') {
+ continue;
+ }
+ if (g == '\\' && curG + 1 < maxG) {
+ curG++;
+ g = pattern.charAt(curG);
+ }
+
+ if (g != value.charAt(curV))
+ return false;
+ }
+ return curG == maxG && curV == maxV;
+ }
}