aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java b/src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java
index 65a2ebd..6f450f1 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java
@@ -4,9 +4,14 @@ import net.minecraft.world.item.ItemStack;
import java.util.HashMap;
import java.util.Map;
+import java.util.function.BiPredicate;
+
import java.util.List;
import net.minecraft.client.Minecraft;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NumericTag;
+import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextColor;
import net.minecraft.resources.ResourceLocation;
@@ -23,13 +28,109 @@ public class Selectors
put("epic", Rarity.EPIC);
}};
+ private static Map<String, BiPredicate<Tag, String>> nbtComparators = new HashMap<String, BiPredicate<Tag, String>>() {{
+ put("=", (tag, value) -> tag.getAsString().contentEquals(value));
+
+ put("!=", (tag, value) -> !tag.getAsString().contentEquals(value));
+
+ put(">", (tag, value) -> {
+ try
+ {
+ double parsedValue = Double.valueOf(value);
+ if (tag instanceof NumericTag)
+ {
+ return ((NumericTag)tag).getAsDouble() > parsedValue;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ });
+
+ put("<", (tag, value) -> {
+ try
+ {
+ double parsedValue = Double.valueOf(value);
+ if (tag instanceof NumericTag)
+ {
+ return ((NumericTag)tag).getAsDouble() < parsedValue;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ });
+ }};
+
+ /**
+ * Returns true if this selector is syntactically valid.
+ * @param value The selector.
+ * @return True if the selector syntax is valid, false otherwise.
+ */
+ public static boolean validateSelector(String value)
+ {
+ // This is a tag, which should be a resource location.
+ if (value.startsWith("$"))
+ {
+ return ResourceLocation.isValidResourceLocation(value.substring(1));
+ }
+ // Mod IDs need to conform to this regex: ^[a-z][a-z0-9_-]{1,63}$
+ else if (value.startsWith("@"))
+ {
+ return value.substring(1).matches("^[a-z][a-z0-9_-]{1,63}$");
+ }
+ // If this is a rarity, make sure it's a valid one.
+ else if (value.startsWith("!"))
+ {
+ return rarities.keySet().contains(value.substring(1).toLowerCase());
+ }
+ // If this is a hex color, ensure it's in a valid format.
+ else if (value.startsWith("#"))
+ {
+ return TextColor.parseColor(value) != null;
+ }
+ // Text matches are always considered valid.
+ else if (value.startsWith("%") || value.startsWith("^"))
+ {
+ return true;
+ }
+ // Any text is valid for NBT tag selectors.
+ else if (value.startsWith("&"))
+ {
+ return true;
+ }
+ // Otherwise it's an item, so just make sure it's a value resource location.
+ else
+ {
+ return value == null || value == "" || ResourceLocation.isValidResourceLocation(value);
+ }
+ }
+
+ /**
+ * Returns true if the given item is matched by the given selector.
+ * @param item An ItemStack instance of an item to check.
+ * @param selector A selector string to check against.
+ * @return True if the item matches, false otherwise.
+ */
public static boolean itemMatches(ItemStack item, String selector)
{
String itemResourceLocation = item.getItem().getRegistryName().toString();
+ // Item ID
if (selector.equals(itemResourceLocation) || selector.equals(itemResourceLocation.replace("minecraft:", "")))
{
return true;
}
+ // Item name color
else if (selector.startsWith("#"))
{
TextColor entryColor = TextColor.parseColor(selector);
@@ -38,6 +139,7 @@ public class Selectors
return true;
}
}
+ // Vanilla rarity
else if (selector.startsWith("!"))
{
if (item.getRarity() == rarities.get(selector.substring(1)))
@@ -45,6 +147,7 @@ public class Selectors
return true;
}
}
+ // Mod ID
else if (selector.startsWith("@"))
{
if (itemResourceLocation.startsWith(selector.substring(1) + ":"))
@@ -52,6 +155,7 @@ public class Selectors
return true;
}
}
+ // Item tag
else if (selector.startsWith("$"))
{
if (ItemTags.getAllTags().getTagOrEmpty(new ResourceLocation(selector.substring(1))).getValues().contains(item.getItem()))
@@ -59,6 +163,7 @@ public class Selectors
return true;
}
}
+ // Item display name
else if (selector.startsWith("%"))
{
if (item.getDisplayName().getString().contains(selector.substring(1)))
@@ -66,6 +171,7 @@ public class Selectors
return true;
}
}
+ // Tooltip text
else if (selector.startsWith("^"))
{
Minecraft mc = Minecraft.getInstance();
@@ -82,7 +188,81 @@ public class Selectors
return true;
}
}
+ // NBT tag
+ else if (selector.startsWith("&"))
+ {
+ String tagName = selector.substring(1);
+ String tagValue = null;
+ BiPredicate<Tag, String> valueChecker = null;
+
+ // This implementation means tag names containing and comparator strings can't be compared.
+ // Hopefully this isn't common.
+ for (String comparator : nbtComparators.keySet())
+ {
+ if (tagName.contains(comparator))
+ {
+ valueChecker = nbtComparators.get(comparator);
+ String[] components = tagName.split(comparator);
+ tagName = components[0];
+ if (components.length > 1)
+ {
+ tagValue = components[1];
+ }
+ break;
+ }
+ }
+
+ // Look for a tag matching the given name.
+ Tag matchedTag = getSubtag(item.getTag(), tagName);
+ if (matchedTag != null)
+ {
+ // A tag value of null means that we are just looking for the presence of this tag.
+ if (tagValue == null)
+ {
+ return true;
+ }
+ // Otherwise, we will use the provided comparator.
+ else
+ {
+ if (valueChecker != null)
+ {
+ return valueChecker.test(matchedTag, tagValue);
+ }
+ }
+ }
+ }
return false;
}
+
+ /**
+ * Retrieves the first inner tag with the given key, or null if there is no match.
+ */
+ private static Tag getSubtag(CompoundTag tag, String key)
+ {
+ if (tag == null)
+ {
+ return null;
+ }
+
+ if (tag.contains(key))
+ {
+ return tag.get(key);
+ }
+ else
+ {
+ for (String innerKey : tag.getAllKeys())
+ {
+ if (tag.getTagType(innerKey) == Tag.TAG_COMPOUND)
+ {
+ Tag innerTag = getSubtag(tag.getCompound(innerKey), key);
+ if (innerTag != null)
+ {
+ return innerTag;
+ }
+ }
+ }
+ return null;
+ }
+ }
} \ No newline at end of file