diff options
Diffstat (limited to 'defaults/src/main/java')
36 files changed, 2713 insertions, 0 deletions
diff --git a/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionDamage.java b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionDamage.java new file mode 100644 index 0000000..c5c31f9 --- /dev/null +++ b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionDamage.java @@ -0,0 +1,46 @@ +package shcm.shsupercm.fabric.citresewn.defaults.cit.conditions; + +import io.shcm.shsupercm.fabric.fletchingtable.api.Entrypoint; +import shcm.shsupercm.fabric.citresewn.api.CITConditionContainer; +import shcm.shsupercm.fabric.citresewn.cit.CITCondition; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.cit.builtin.conditions.IntegerCondition; + +import java.util.Set; + +public class ConditionDamage extends IntegerCondition { + @Entrypoint(CITConditionContainer.ENTRYPOINT) + public static final CITConditionContainer<ConditionDamage> CONTAINER = new CITConditionContainer<>(ConditionDamage.class, ConditionDamage::new, + "damage"); + + protected Integer mask = null; + + public ConditionDamage() { + super(true, false, true); + } + + @Override + protected int getValue(CITContext context) { + int value = context.stack.isDamageable() ? context.stack.getDamage() : 0; + if (mask != null) + value &= mask; + return value; + } + + @Override + protected int getPercentageTotalValue(CITContext context) { + return context.stack.isDamageable() ? context.stack.getItem().getMaxDamage() : 0; + } + + @Override + public Set<Class<? extends CITCondition>> siblingConditions() { + return Set.of(ConditionDamageMask.class); + } + + @Override + public <T extends CITCondition> T modifySibling(T sibling) { + if (sibling instanceof ConditionDamageMask damageMask) + this.mask = damageMask.getMask(); + return null; + } +} diff --git a/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionDamageMask.java b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionDamageMask.java new file mode 100644 index 0000000..6adde08 --- /dev/null +++ b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionDamageMask.java @@ -0,0 +1,38 @@ +package shcm.shsupercm.fabric.citresewn.defaults.cit.conditions; + +import io.shcm.shsupercm.fabric.fletchingtable.api.Entrypoint; +import shcm.shsupercm.fabric.citresewn.api.CITConditionContainer; +import shcm.shsupercm.fabric.citresewn.cit.CITCondition; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.cit.builtin.conditions.IntegerCondition; + +import java.util.Set; + +public class ConditionDamageMask extends IntegerCondition { + @Entrypoint(CITConditionContainer.ENTRYPOINT) + public static final CITConditionContainer<ConditionDamageMask> CONTAINER = new CITConditionContainer<>(ConditionDamageMask.class, ConditionDamageMask::new, + "damage_mask", "damageMask"); + + public ConditionDamageMask() { + super(false, false, false); + } + + @Override + protected int getValue(CITContext context) { + return 0; + } + + @Override + public boolean test(CITContext context) { + return true; + } + + public int getMask() { + return this.min; + } + + @Override + public Set<Class<? extends CITCondition>> siblingConditions() { + return Set.of(ConditionDamage.class); + } +} diff --git a/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionEnchantmentLevels.java b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionEnchantmentLevels.java new file mode 100644 index 0000000..da6b4f4 --- /dev/null +++ b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionEnchantmentLevels.java @@ -0,0 +1,62 @@ +package shcm.shsupercm.fabric.citresewn.defaults.cit.conditions; + +import io.shcm.shsupercm.fabric.fletchingtable.api.Entrypoint; +import net.minecraft.util.Identifier; +import shcm.shsupercm.fabric.citresewn.api.CITConditionContainer; +import shcm.shsupercm.fabric.citresewn.cit.CITCondition; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.cit.builtin.conditions.IntegerCondition; +import shcm.shsupercm.fabric.citresewn.cit.builtin.conditions.ListCondition; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class ConditionEnchantmentLevels extends ListCondition<ConditionEnchantmentLevels.EnchantmentLevelCondition> { + @Entrypoint(CITConditionContainer.ENTRYPOINT) + public static final CITConditionContainer<ConditionEnchantmentLevels> CONTAINER = new CITConditionContainer<>(ConditionEnchantmentLevels.class, ConditionEnchantmentLevels::new, + "enchantment_levels", "enchantmentLevels"); + + protected Set<Identifier> enchantments = null; + + public ConditionEnchantmentLevels() { + super(EnchantmentLevelCondition.class, EnchantmentLevelCondition::new); + } + + @Override + public Set<Class<? extends CITCondition>> siblingConditions() { + return Set.of(ConditionEnchantments.class); + } + + @Override + public <T extends CITCondition> T modifySibling(T sibling) { + if (sibling instanceof ConditionEnchantments conditionEnchantments) { + if (enchantments == null) { + enchantments = new HashSet<>(); + for (EnchantmentLevelCondition subCondition : this.conditions) + subCondition.enchantments = enchantments; + } + enchantments.addAll(Arrays.asList(conditionEnchantments.getEnchantments())); + } + + return sibling; + } + + protected static class EnchantmentLevelCondition extends IntegerCondition { + protected Set<Identifier> enchantments = null; + + protected EnchantmentLevelCondition() { + super(true, false, false); + } + + @Override + public boolean test(CITContext context) { + for (Map.Entry<Identifier, Integer> entry : context.enchantments().entrySet()) + if ((enchantments == null || enchantments.contains(entry.getKey())) && entry.getValue() != null && (range ? min <= entry.getValue() && entry.getValue() <= max : entry.getValue() == min)) + return true; + + return false; + } + } +} diff --git a/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionEnchantments.java b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionEnchantments.java new file mode 100644 index 0000000..301f9c1 --- /dev/null +++ b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionEnchantments.java @@ -0,0 +1,59 @@ +package shcm.shsupercm.fabric.citresewn.defaults.cit.conditions; + +import io.shcm.shsupercm.fabric.fletchingtable.api.Entrypoint; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import shcm.shsupercm.fabric.citresewn.api.CITConditionContainer; +import shcm.shsupercm.fabric.citresewn.cit.CITCondition; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.cit.builtin.conditions.IdentifierCondition; +import shcm.shsupercm.fabric.citresewn.cit.builtin.conditions.ListCondition; +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.util.Set; + +public class ConditionEnchantments extends ListCondition<ConditionEnchantments.EnchantmentCondition> { + @Entrypoint(CITConditionContainer.ENTRYPOINT) + public static final CITConditionContainer<ConditionEnchantments> CONTAINER = new CITConditionContainer<>(ConditionEnchantments.class, ConditionEnchantments::new, + "enchantments", "enchantmentIDs"); + + public ConditionEnchantments() { + super(EnchantmentCondition.class, EnchantmentCondition::new); + } + + public Identifier[] getEnchantments() { + Identifier[] enchantments = new Identifier[this.conditions.length]; + + for (int i = 0; i < this.conditions.length; i++) + enchantments[i] = this.conditions[i].getValue(null); + + return enchantments; + } + + @Override + public Set<Class<? extends CITCondition>> siblingConditions() { + return Set.of(ConditionEnchantmentLevels.class); + } + + protected static class EnchantmentCondition extends IdentifierCondition { + @Override + public void load(PropertyValue value, PropertyGroup properties) throws CITParsingException { + super.load(value, properties); + + if (!Registry.ENCHANTMENT.containsId(this.value)) + warn(this.value + " is not in the enchantment registry", value, properties); + } + + @Override + public boolean test(CITContext context) { + return context.enchantments().containsKey(this.value); + } + + @Override + protected Identifier getValue(CITContext context) { + return this.value; + } + } +} diff --git a/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionHand.java b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionHand.java new file mode 100644 index 0000000..0405cbc --- /dev/null +++ b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionHand.java @@ -0,0 +1,49 @@ +package shcm.shsupercm.fabric.citresewn.defaults.cit.conditions; + +import io.shcm.shsupercm.fabric.fletchingtable.api.Entrypoint; +import shcm.shsupercm.fabric.citresewn.api.CITConditionContainer; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.cit.builtin.conditions.EnumCondition; + +public class ConditionHand extends EnumCondition<ConditionHand.Hand> { + @Entrypoint(CITConditionContainer.ENTRYPOINT) + public static final CITConditionContainer<ConditionHand> CONTAINER = new CITConditionContainer<>(ConditionHand.class, ConditionHand::new, + "hand"); + + public ConditionHand() { + super(ConditionHand.Hand::values); + } + + @Override + protected Hand getValue(CITContext context) { + if (context.entity.getMainHandStack() == context.stack) + return Hand.MAINHAND; + if (context.entity.getOffHandStack() == context.stack) + return Hand.OFFHAND; + + return null; + } + + @Override + public boolean test(CITContext context) { + Hand hand = getValue(context); + return this.value == hand || (this.value == Hand.ANY && hand != null); + } + + protected enum Hand implements EnumCondition.Aliased { + MAINHAND("main", "mainhand", "main_hand"), + OFFHAND("off", "offhand", "off_hand"), + ANY("any", "either", "*"); + + private final String[] aliases; + + Hand(String... aliases) { + this.aliases = aliases; + } + + @Override + public String[] getAliases() { + return this.aliases; + } + } +} diff --git a/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionItems.java b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionItems.java new file mode 100644 index 0000000..117aa47 --- /dev/null +++ b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionItems.java @@ -0,0 +1,75 @@ +package shcm.shsupercm.fabric.citresewn.defaults.cit.conditions; + +import io.shcm.shsupercm.fabric.fletchingtable.api.Entrypoint; +import net.minecraft.item.Item; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import shcm.shsupercm.fabric.citresewn.api.CITConditionContainer; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.cit.builtin.conditions.IdentifierCondition; +import shcm.shsupercm.fabric.citresewn.cit.builtin.conditions.ListCondition; +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.util.LinkedHashSet; +import java.util.Set; + +public class ConditionItems extends ListCondition<ConditionItems.ItemCondition> { + @Entrypoint(CITConditionContainer.ENTRYPOINT) + public static final CITConditionContainer<ConditionItems> CONTAINER = new CITConditionContainer<>(ConditionItems.class, ConditionItems::new, + "items", "matchItems"); + + public Item[] items = new Item[0]; + + public ConditionItems() { + super(ItemCondition.class, ItemCondition::new); + } + + public ConditionItems(Item... items) { + this(); + this.items = items; + } + + @Override + public void load(PropertyValue value, PropertyGroup properties) throws CITParsingException { + super.load(value, properties); + + Set<Item> items = new LinkedHashSet<>(); + + for (ItemCondition itemCondition : this.conditions) + items.add(itemCondition.item); + + this.items = items.toArray(new Item[0]); + } + + @Override + public boolean test(CITContext context) { + for (Item item : this.items) + if (context.stack.getItem() == item) + return true; + + return false; + } + + protected static class ItemCondition extends IdentifierCondition { + public Item item = null; + + @Override + public void load(PropertyValue value, PropertyGroup properties) throws CITParsingException { + super.load(value, properties); + + if (Registry.ITEM.containsId(this.value)) + this.item = Registry.ITEM.get(this.value); + else { + this.item = null; + warn(this.value + " is not in the item registry", value, properties); + } + } + + @Override + protected Identifier getValue(CITContext context) { + return this.value; + } + } +} diff --git a/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionNBT.java b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionNBT.java new file mode 100644 index 0000000..09ae08e --- /dev/null +++ b/defaults/src/main/java/shcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionNBT.java @@ -0,0 +1,244 @@ +package shcm.shsupercm.fabric.citresewn.defaults.cit.conditions; + +import io.shcm.shsupercm.fabric.fletchingtable.api.Entrypoint; +import net.minecraft.nbt.*; +import net.minecraft.text.Text; +import shcm.shsupercm.fabric.citresewn.api.CITConditionContainer; +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.util.Locale; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +public class ConditionNBT extends CITCondition { + @Entrypoint(CITConditionContainer.ENTRYPOINT) + public static final CITConditionContainer<ConditionNBT> CONTAINER = new CITConditionContainer<>(ConditionNBT.class, ConditionNBT::new, + "nbt"); + + protected String[] path; + + protected StringMatcher matchString = null; + protected NbtInt matchInteger = null; + protected NbtByte matchByte = null; + protected NbtFloat matchFloat = null; + protected NbtDouble matchDouble = null; + protected NbtLong matchLong = null; + protected NbtShort matchShort = null; + protected NbtCompound matchCompound = null; + + @Override + public void load(PropertyValue value, PropertyGroup properties) throws CITParsingException { + if (value.keyMetadata() == null || value.keyMetadata().isEmpty()) + throw new CITParsingException("Missing nbt path", properties, value.position()); + + path = value.keyMetadata().split("\\."); + for (String s : path) + if (s.isEmpty()) + throw new CITParsingException("Path segment cannot be empty", properties, value.position()); + + try { + if (value.value().startsWith("regex:")) + matchString = new StringMatcher.RegexMatcher(value.value().substring(6)); + else if (value.value().startsWith("iregex:")) + matchString = new StringMatcher.IRegexMatcher(value.value().substring(7)); + else if (value.value().startsWith("pattern:")) + matchString = new StringMatcher.PatternMatcher(value.value().substring(8)); + else if (value.value().startsWith("ipattern:")) + matchString = new StringMatcher.IPatternMatcher(value.value().substring(9)); + else + matchString = new StringMatcher.DirectMatcher(value.value()); + } catch (PatternSyntaxException e) { + throw new CITParsingException("Malformatted regex expression", properties, value.position(), e); + } catch (Exception ignored) { } + try { + if (value.value().startsWith("#")) + matchInteger = NbtInt.of(Integer.parseInt(value.value().substring(1).toLowerCase(Locale.ENGLISH), 16)); + else if (value.value().startsWith("0x")) + matchInteger = NbtInt.of(Integer.parseInt(value.value().substring(2).toLowerCase(Locale.ENGLISH), 16)); + else + matchInteger = NbtInt.of(Integer.parseInt(value.value())); + } catch (Exception ignored) { } + try { + matchByte = NbtByte.of(Byte.parseByte(value.value())); + } catch (Exception ignored) { } + try { + matchFloat = NbtFloat.of(Float.parseFloat(value.value())); + } catch (Exception ignored) { } + try { + matchDouble = NbtDouble.of(Double.parseDouble(value.value())); + } catch (Exception ignored) { } + try { + matchLong = NbtLong.of(Long.parseLong(value.value())); + } catch (Exception ignored) { } + try { + matchShort = NbtShort.of(Short.parseShort(value.value())); + } catch (Exception ignored) { } + try { + matchCompound = StringNbtReader.parse(value.value()); + } catch (Exception ignored) { } + } + + @Override + public boolean test(CITContext context) { + return testPath(context.stack.getNbt(), 0); + } + + protected boolean testPath(NbtElement element, int pathIndex) { + if (element == null) + return false; + + if (pathIndex >= path.length) + return testValue(element); + + final String path = this.path[pathIndex]; + if (path.equals("*")) { + if (element instanceof NbtCompound compound) { + for (NbtElement subElement : compound.entries.values()) + if (testPath(subElement, pathIndex + 1)) + return true; + } else if (element instanceof NbtList list) { + for (NbtElement subElement : list) + if (testPath(subElement, pathIndex + 1)) + return true; + } + } else { + if (element instanceof NbtCompound compound) + return testPath(compound.get(path), pathIndex + 1); + else if (element instanceof NbtList list) + try { + return testPath(list.get(Integer.parseInt(path)), pathIndex + 1); + } catch (NumberFormatException | IndexOutOfBoundsException ignored) { } + } + + return false; + } + + private boolean testValue(NbtElement element) { + try { + if (element instanceof NbtString nbtString) //noinspection ConstantConditions + return matchString.matches(nbtString.asString()) || matchString.matches(Text.Serializer.fromJson(nbtString.asString()).getString()); + else if (element instanceof NbtInt nbtInt) + return nbtInt.equals(matchInteger); + else if (element instanceof NbtByte nbtByte) + return nbtByte.equals(matchByte); + else if (element instanceof NbtFloat nbtFloat) + return nbtFloat.equals(matchFloat); + else if (element instanceof NbtDouble nbtDouble) + return nbtDouble.equals(matchDouble); + else if (element instanceof NbtLong nbtLong) + return nbtLong.equals(matchLong); + else if (element instanceof NbtShort nbtShort) + return nbtShort.equals(matchShort); + else if (element instanceof NbtCompound nbtCompound) + return NbtHelper.matches(matchCompound, nbtCompound, true); + } catch (Exception ignored) { } + return false; + } + + protected static abstract class StringMatcher { + public abstract boolean matches(String value); + + public static class DirectMatcher extends StringMatcher { + protected final String pattern; + + public DirectMatcher(String pattern) { + this.pattern = pattern; + } + + @Override + public boolean matches(String value) { + return pattern.equals(value); + } + } + + public static class RegexMatcher extends StringMatcher { + protected final Pattern pattern; + + public RegexMatcher(String pattern) { + this(Pattern.compile(pattern)); + } + + protected RegexMatcher(Pattern pattern) { + this.pattern = pattern; + } + + @Override + public boolean matches(String value) { + return this.pattern.matcher(value).matches(); + } + } + + public static class PatternMatcher extends StringMatcher { + protected final String pattern; + + public PatternMatcher(String pattern) { + this.pattern = pattern; + } + + @Override + public boolean matches(String value) { + return matchesPattern(value, this.pattern, 0, value.length(), 0, pattern.length()); + } + + /** + * Author: Paul "prupe" Rupe<br> + * Taken and modified 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 + */ + protected 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 (!charsEqual(g, value.charAt(curV))) + return false; + } + return curG == maxG && curV == maxV; + } + + protected boolean charsEqual(char p, char v) { + return p == v; + } + } + + public static class IRegexMatcher extends RegexMatcher { + public IRegexMatcher(String pattern) { + super(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); + } + } + + public static class IPatternMatcher extends PatternMatcher { + public IPatternMatcher(String pattern) { + super(pattern.toLowerCase(Locale.ROOT)); + } + + @Override + protected boolean charsEqual(char p, char v) { + return p == v || p == Character.toLowerCase(v); + } + } + } |
