diff options
author | SHsuperCM <shsupercm@gmail.com> | 2021-08-21 10:57:40 +0300 |
---|---|---|
committer | SHsuperCM <shsupercm@gmail.com> | 2021-08-21 10:57:40 +0300 |
commit | 9d5a632898e886ba0081e189dc88c9ffbaaa8e3b (patch) | |
tree | 4012903d4fe3515a6771828d90266900b35f136d /src/main/java | |
parent | 676c5fafb20591f3f3a61843b87d75372f77c120 (diff) | |
download | CITResewn-9d5a632898e886ba0081e189dc88c9ffbaaa8e3b.tar.gz CITResewn-9d5a632898e886ba0081e189dc88c9ffbaaa8e3b.tar.bz2 CITResewn-9d5a632898e886ba0081e189dc88c9ffbaaa8e3b.zip |
Parse nbt
Diffstat (limited to 'src/main/java')
-rw-r--r-- | src/main/java/shcm/shsupercm/fabric/citresewn/mixin/NbtCompoundAccessor.java | 14 | ||||
-rw-r--r-- | src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java | 109 |
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; + } } |