aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java176
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java24
-rw-r--r--src/main/resources/iceberg.mixins.json6
3 files changed, 196 insertions, 10 deletions
diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java b/src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java
index 5fcaf41..af5c3af 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java
@@ -5,9 +5,13 @@ 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;
@@ -24,6 +28,100 @@ 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 = Registry.ITEM.getKey(item.getItem()).toString();
@@ -36,7 +134,7 @@ public class Selectors
else if (selector.startsWith("#"))
{
TextColor entryColor = TextColor.parseColor(selector);
- if (entryColor.equals(ItemColor.getColorForItem(item, TextColor.fromRgb(0xFFFFFF))))
+ if (entryColor != null && entryColor.equals(ItemColor.getColorForItem(item, TextColor.fromRgb(0xFFFFFF))))
{
return true;
}
@@ -90,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
diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java
index 27d7c87..ec1dfc4 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java
@@ -126,17 +126,24 @@ public class Tooltips
initialized = true;
}
- public static void renderItemTooltip(final ItemStack stack, PoseStack mStack, TooltipInfo info,
- Rect2i rect, int screenWidth, int screenHeight,
- int backgroundColor, int borderColorStart, int borderColorEnd)
+ public static void renderItemTooltip(final ItemStack stack, PoseStack poseStack, TooltipInfo info,
+ Rect2i rect, int screenWidth, int screenHeight,
+ int backgroundColor, int borderColorStart, int borderColorEnd)
{
- renderItemTooltip(stack, mStack, info, rect, screenWidth, screenHeight, backgroundColor, borderColorStart, borderColorEnd, false);
+ renderItemTooltip(stack, poseStack, info, rect, screenWidth, screenHeight, backgroundColor, borderColorStart, borderColorEnd, false);
}
public static void renderItemTooltip(final ItemStack stack, PoseStack poseStack, TooltipInfo info,
Rect2i rect, int screenWidth, int screenHeight,
int backgroundColor, int borderColorStart, int borderColorEnd, boolean comparison)
{
+ renderItemTooltip(stack, poseStack, info, rect, screenWidth, screenHeight, backgroundColor, borderColorStart, borderColorEnd, comparison, false);
+ }
+
+ public static void renderItemTooltip(final ItemStack stack, PoseStack poseStack, TooltipInfo info,
+ Rect2i rect, int screenWidth, int screenHeight,
+ int backgroundColor, int borderColorStart, int borderColorEnd, boolean comparison, boolean constrain)
+ {
// Initialize if needed.
if (!initialized)
{
@@ -162,6 +169,13 @@ public class Tooltips
int tooltipX = rectX + 12;
int tooltipTextWidth = info.getMaxLineWidth();
+
+ // Constrain the minimum width to the rect.
+ if (constrain)
+ {
+ tooltipTextWidth = Math.max(info.getMaxLineWidth(), rect.getWidth() - 8);
+ }
+
if (tooltipX + tooltipTextWidth + 4 > screenWidth)
{
tooltipX = rectX - 16 - tooltipTextWidth;
@@ -277,7 +291,7 @@ public class Tooltips
RenderTooltipEvents.POST.invoker().onPost(stack, info.getLines(), poseStack, tooltipX, tooltipY, info.getFont(), tooltipTextWidth, tooltipHeight, comparison);
}
- public static Rect2i calculateRect(final ItemStack stack, PoseStack mStack, List<ClientTooltipComponent> textLines, int mouseX, int mouseY,
+ public static Rect2i calculateRect(final ItemStack stack, PoseStack poseStack, List<ClientTooltipComponent> textLines, int mouseX, int mouseY,
int screenWidth, int screenHeight, int maxTextWidth, Font font)
{
Rect2i rect = new Rect2i(0, 0, 0, 0);
diff --git a/src/main/resources/iceberg.mixins.json b/src/main/resources/iceberg.mixins.json
index e1b0432..758fce2 100644
--- a/src/main/resources/iceberg.mixins.json
+++ b/src/main/resources/iceberg.mixins.json
@@ -5,13 +5,13 @@
"verbose": true,
"mixins": [
"EntityMixin",
- "PlayerAdvancementsMixin",
- "MinecraftMixin"
+ "PlayerAdvancementsMixin"
],
"client": [
"ScreenMixin",
"ClientPacketListenerMixin",
- "LivingEntityMixin"
+ "LivingEntityMixin",
+ "MinecraftMixin"
],
"injectors": {
"defaultRequire": 1