diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/BukkitScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/BukkitScriptEvent.java index 2070932cb3..95a2b20656 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/events/BukkitScriptEvent.java +++ b/plugin/src/main/java/com/denizenscript/denizen/events/BukkitScriptEvent.java @@ -7,6 +7,7 @@ import com.denizenscript.denizen.scripts.containers.core.InventoryScriptHelper; import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper; import com.denizenscript.denizen.tags.BukkitTagContext; +import com.denizenscript.denizen.utilities.VanillaTagHelper; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.flags.AbstractFlagTracker; import com.denizenscript.denizencore.objects.core.ScriptTag; @@ -43,12 +44,14 @@ public abstract class BukkitScriptEvent extends ScriptEvent { // // "" usually indicates that a MaterialTag will be matched against. // This means you can specify any valid block material name, like "stone" or "air". + // You can also use "vanilla_tagged:". // You can also use "block" or "material" as catch-alls. // // "" or similar expects of course an ItemTag. // You can use any valid item material type like "stick", or the name of an item script, or "item" as a catch-all, or "potion" for any potion item. // Items can also be used with an "item_flagged" secondary prefix, so for an event that has "with:", you can also do "with:item_flagged:". // For item matchers that aren't switches, this works similarly, like "on player consumes item_flagged:myflag:" (note that this is not a switch). + // You can also use "vanilla_tagged:". // // "", "", "", etc. are examples of where an EntityTag will be expected. // You can generally specify any potentially relevant entity type, such as "creeper" under "", or "arrow" for "", @@ -255,7 +258,7 @@ public boolean couldMatchVehicle(String text) { } public boolean couldMatchBlockOrItem(String text) { - if (text.equals("block") || text.equals("material") || text.equals("item") || text.equals("potion") || text.startsWith("item_flagged:")) { + if (text.equals("block") || text.equals("material") || text.equals("item") || text.equals("potion") || text.startsWith("item_flagged:") || text.startsWith("vanilla_tagged:")) { return true; } if (MaterialTag.matches(text)) { @@ -285,7 +288,7 @@ public boolean couldMatchBlockOrItem(String text) { } public boolean couldMatchBlock(String text) { - if (text.equals("block") || text.equals("material")) { + if (text.equals("block") || text.equals("material") || text.startsWith("vanilla_tagged:")) { return true; } if (text.equals("item")) { @@ -313,7 +316,7 @@ public boolean couldMatchItem(String text) { if (text.equals("item") || text.equals("potion")) { return true; } - if (text.startsWith("item_flagged:")) { + if (text.startsWith("item_flagged:") || text.startsWith("vanilla_tagged:")) { return true; } if (MaterialTag.matches(text)) { @@ -913,6 +916,20 @@ public static boolean tryItem(ItemTag item, String comparedto) { } return true; } + if (comparedto.startsWith("vanilla_tagged:")) { + String tagCheck = comparedto.substring("vanilla_tagged:".length()); + HashSet tags = VanillaTagHelper.tagsByMaterial.get(item.getItemStack().getType()); + if (tags == null) { + return false; + } + MatchHelper matcher = createMatcher(tagCheck); + for (String tag : tags) { + if (matcher.doesMatch(tag)) { + return true; + } + } + return false; + } if (comparedto.equals("item")) { return true; } @@ -934,6 +951,10 @@ public static boolean tryItem(ItemTag item, String comparedto) { } public static boolean tryMaterial(MaterialTag mat, String comparedto) { + return tryMaterial(mat.getMaterial(), comparedto); + } + + public static boolean tryMaterial(Material mat, String comparedto) { if (comparedto == null || comparedto.isEmpty() || mat == null) { return false; } @@ -941,9 +962,23 @@ public static boolean tryMaterial(MaterialTag mat, String comparedto) { if (comparedto.equals("block") || comparedto.equals("material")) { return true; } + if (comparedto.startsWith("vanilla_tagged:")) { + String tagCheck = comparedto.substring("vanilla_tagged:".length()); + HashSet tags = VanillaTagHelper.tagsByMaterial.get(mat); + if (tags == null) { + return false; + } + MatchHelper matcher = createMatcher(tagCheck); + for (String tag : tags) { + if (matcher.doesMatch(tag)) { + return true; + } + } + return false; + } MaterialTag quickOf = MaterialTag.quickOfNamed(comparedto); if (quickOf != null) { - if (quickOf.getMaterial() != mat.getMaterial()) { + if (quickOf.getMaterial() != mat) { return false; } if (quickOf.equals(mat)) { diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/MaterialTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/MaterialTag.java index 7416851a41..9f3dbc6c8b 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/MaterialTag.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/MaterialTag.java @@ -2,6 +2,7 @@ import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.properties.material.*; +import com.denizenscript.denizen.utilities.VanillaTagHelper; import com.denizenscript.denizen.utilities.debugging.Debug; import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.flags.AbstractFlagTracker; @@ -12,18 +13,22 @@ import com.denizenscript.denizen.tags.BukkitTagContext; import com.denizenscript.denizencore.objects.core.DurationTag; import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.denizenscript.denizencore.tags.Attribute; import com.denizenscript.denizencore.tags.ObjectTagProcessor; import com.denizenscript.denizencore.tags.TagContext; import com.denizenscript.denizencore.tags.TagRunnable; import com.denizenscript.denizencore.utilities.CoreUtilities; +import com.denizenscript.denizencore.utilities.Deprecations; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.data.BlockData; import org.bukkit.inventory.meta.BlockStateMeta; +import java.util.HashSet; + public class MaterialTag implements ObjectTag, Adjustable, FlaggableObject { // <--[language] @@ -690,14 +695,8 @@ public static void registerTags() { return new ElementTag(res); }); - // <--[tag] - // @attribute ]> - // @returns ElementTag(Boolean) - // @description - // Returns whether this material has the specified Minecraft vanilla Data Pack Tag. - // See <@link url https://minecraft.gamepedia.com/Tag>. - // --> registerTag("has_vanilla_data_tag", (attribute, object) -> { + Deprecations.materialHasDataPackTag.warn(attribute.context); if (!attribute.hasContext(1)) { attribute.echoError("MaterialTag.has_vanilla_data_tag[...] tag must have an input value."); return null; @@ -711,7 +710,6 @@ public static void registerTags() { // <--[tag] // @attribute ]> // @returns ElementTag(Boolean) - // @group element checking // @description // Returns whether the material matches some matcher text, using the system behind <@link language Advanced Script Event Matching>. // --> @@ -721,6 +719,20 @@ public static void registerTags() { } return new ElementTag(BukkitScriptEvent.tryMaterial(object, attribute.getContext(1))); }); + + // <--[tag] + // @attribute + // @returns ListTag + // @description + // Returns a list of vanilla tags that apply to this material. See also <@link url https://minecraft.fandom.com/wiki/Tag>. + // --> + registerTag("vanilla_tags", (attribute, object) -> { + HashSet tags = VanillaTagHelper.tagsByMaterial.get(object.getMaterial()); + if (tags == null) { + return null; + } + return new ListTag(tags); + }); } public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>(); diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptHelper.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptHelper.java index 3b676e2747..6a5cd245f1 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptHelper.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptHelper.java @@ -1,5 +1,7 @@ package com.denizenscript.denizen.scripts.containers.core; + import com.denizenscript.denizen.Denizen; +import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.nms.util.jnbt.CompoundTag; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.debugging.Debug; @@ -94,16 +96,15 @@ public ItemStack[] textToItemArray(ItemScriptContainer container, String text, b String entry = ingredientText.get(i); if (ScriptEvent.isAdvancedMatchable(entry)) { boolean any = false; - ScriptEvent.MatchHelper matcher = ScriptEvent.createMatcher(entry); for (Material material : Material.values()) { - if (matcher.doesMatch(CoreUtilities.toLowerCase(material.name()))) { + if (BukkitScriptEvent.tryMaterial(material, entry)) { outputItems.add(new ItemStack(material, 1)); any = true; } } if (exact) { for (ItemScriptContainer possibleContainer : ItemScriptHelper.item_scripts.values()) { - if (matcher.doesMatch(CoreUtilities.toLowerCase(possibleContainer.getName()))) { + if (BukkitScriptEvent.tryItem(possibleContainer.getCleanReference(), entry)) { outputItems.add(possibleContainer.getCleanReference().getItemStack()); any = true; } diff --git a/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java b/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java index b5b9dc5808..f8d5b94ab6 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java +++ b/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java @@ -8,6 +8,7 @@ import com.denizenscript.denizen.scripts.containers.core.CommandScriptHelper; import com.denizenscript.denizen.utilities.ScoreboardHelper; import com.denizenscript.denizen.utilities.Utilities; +import com.denizenscript.denizen.utilities.VanillaTagHelper; import com.denizenscript.denizen.utilities.debugging.Debug; import com.denizenscript.denizen.utilities.depends.Depends; import com.denizenscript.denizen.utilities.inventory.SlotHelper; @@ -2083,6 +2084,37 @@ else if (attribute.startsWith("last_reload")) { event.setReplacedObject(new TimeTag(Denizen.getInstance().lastReloadTime).getObjectAttribute(attribute.fulfill(1))); } + // <--[tag] + // @attribute + // @returns ListTag + // @description + // Returns a list of vanilla tags (applicable to blocks, fluids, or items). See also <@link url https://minecraft.fandom.com/wiki/Tag>. + // --> + else if (attribute.startsWith("vanilla_tags")) { + event.setReplacedObject(new ListTag(VanillaTagHelper.tagsByKey.keySet()).getObjectAttribute(attribute.fulfill(1))); + } + + // <--[tag] + // @attribute ]> + // @returns ListTag(MaterialTag) + // @description + // Returns a list of materials referred to by the specified vanilla tag. See also <@link url https://minecraft.fandom.com/wiki/Tag>. + // --> + else if (attribute.startsWith("vanilla_tagged_materials")) { + if (!attribute.hasContext(1)) { + return; + } + HashSet materials = VanillaTagHelper.tagsByKey.get(CoreUtilities.toLowerCase(attribute.getContext(1))); + if (materials == null) { + return; + } + ListTag list = new ListTag(); + for (Material material : materials) { + list.addObject(new MaterialTag(material)); + } + event.setReplacedObject(list.getObjectAttribute(attribute.fulfill(1))); + } + // <--[tag] // @attribute ]> // @returns ListTag(PluginTag) diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/VanillaTagHelper.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/VanillaTagHelper.java new file mode 100644 index 0000000000..7a16c59ad4 --- /dev/null +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/VanillaTagHelper.java @@ -0,0 +1,34 @@ +package com.denizenscript.denizen.utilities; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Tag; + +import java.util.HashMap; +import java.util.HashSet; + +public class VanillaTagHelper { + + public static HashMap> tagsByMaterial = new HashMap<>(); + + public static HashMap> tagsByKey = new HashMap<>(); + + static void addTag(Tag tag) { + tagsByKey.computeIfAbsent(tag.getKey().getKey(), (k) -> new HashSet<>()).addAll(tag.getValues()); + for (Material mat : tag.getValues()) { + tagsByMaterial.computeIfAbsent(mat, (k) -> new HashSet<>()).add(tag.getKey().getKey()); + } + } + + static { + for (Tag tag : Bukkit.getTags("blocks", Material.class)) { + addTag(tag); + } + /*for (Tag tag : Bukkit.getTags("fluids", Material.class)) { + addTag(tag); + }*/ // Temporarily exclude fluids due to spigot bug + for (Tag tag : Bukkit.getTags("items", Material.class)) { + addTag(tag); + } + } +}