From 1fd18aeaa6b46f08e0a9d6c97d7183d3767e97f8 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Mon, 21 Feb 2022 15:49:21 +0200 Subject: [PATCH] Update potion effect properties to modern format (#2325) * Start on effect_mao * Finish update * Fix sub-tags * Small fixes --- .../denizen/nms/interfaces/ItemHelper.java | 2 - .../entity/EntityPotionEffects.java | 121 ++-- .../objects/properties/item/ItemPotion.java | 588 +++++++++++------- .../nms/v1_16/helpers/ItemHelperImpl.java | 7 - .../nms/v1_17/helpers/ItemHelperImpl.java | 7 - .../nms/v1_18/helpers/ItemHelperImpl.java | 7 - 6 files changed, 446 insertions(+), 286 deletions(-) diff --git a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java index d72c66ae11..37b57ae57d 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java +++ b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java @@ -60,8 +60,6 @@ public void registerStonecuttingRecipe(String keyName, String group, ItemStack r public abstract ItemStack setNbtData(ItemStack itemStack, CompoundTag compoundTag); - public abstract PotionEffect getPotionEffect(PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon); - public void registerSmithingRecipe(String keyName, ItemStack result, ItemStack[] baseItem, boolean baseExact, ItemStack[] upgradeItem, boolean upgradeExact) { throw new UnsupportedOperationException(); } diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityPotionEffects.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityPotionEffects.java index 7d646ff42f..9f9220ee53 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityPotionEffects.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityPotionEffects.java @@ -6,8 +6,10 @@ import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.objects.properties.Property; -import com.denizenscript.denizencore.tags.Attribute; +import com.denizenscript.denizencore.objects.properties.PropertyParser; +import com.denizenscript.denizencore.utilities.CoreUtilities; import org.bukkit.entity.Arrow; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -34,10 +36,6 @@ public static EntityPotionEffects getFrom(ObjectTag object) { } } - public static final String[] handledTags = new String[] { - "list_effects", "has_effect" - }; - public static final String[] handledMechs = new String[] { "potion_effects" }; @@ -52,33 +50,46 @@ public Collection getEffectsList() { if (entity.isLivingEntity()) { return entity.getLivingEntity().getActivePotionEffects(); } - else if (entity.getBukkitEntity() instanceof Arrow) { - return ((Arrow) entity.getBukkitEntity()).getCustomEffects(); + else if (isArrow()) { + return getArrow().getCustomEffects(); } return new ArrayList<>(); } - public String getPropertyString() { - Collection effects = getEffectsList(); - if (effects.isEmpty()) { - return null; + public ListTag getEffectsListTag() { + ListTag result = new ListTag(); + for (PotionEffect effect : getEffectsList()) { + result.add(ItemPotion.stringifyEffect(effect)); } - ListTag returnable = new ListTag(); - for (PotionEffect effect : effects) { - returnable.add(ItemPotion.stringifyEffect(effect)); + return result; + } + + public ListTag getEffectsMapTag() { + ListTag result = new ListTag(); + for (PotionEffect effect : getEffectsList()) { + result.addObject(ItemPotion.effectToMap(effect)); } - return returnable.identify(); + return result; + } + + public boolean isArrow() { + return entity.getBukkitEntity() instanceof Arrow; + } + + public Arrow getArrow() { + return (Arrow) entity.getBukkitEntity(); + } + + public String getPropertyString() { + ListTag effects = getEffectsMapTag(); + return effects.isEmpty() ? null : effects.identify(); } public String getPropertyId() { return "potion_effects"; } - public ObjectTag getObjectAttribute(Attribute attribute) { - - if (attribute == null) { - return null; - } + public static void registerTags() { // <--[tag] // @attribute @@ -91,13 +102,21 @@ public ObjectTag getObjectAttribute(Attribute attribute) { // IS_AMBIENT, HAS_PARTICLES, and HAS_ICON are booleans. // The effect type will be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html>. // --> - if (attribute.startsWith("list_effects")) { - ListTag effects = new ListTag(); - for (PotionEffect effect : getEffectsList()) { - effects.add(ItemPotion.stringifyEffect(effect)); - } - return effects.getObjectAttribute(attribute.fulfill(1)); - } + PropertyParser.registerTag(ListTag.class, "list_effects", (attribute, object) -> { + return object.getEffectsListTag(); + }); + + // <--[tag] + // @attribute + // @returns ListTag(MapTag) + // @group attribute + // @mechanism EntityTag.potion_effects + // @description + // Returns the active potion effects on the entity, in the MapTag format of the mechanism. + // --> + PropertyParser.registerTag(ListTag.class, "effects_data", (attribute, object) -> { + return object.getEffectsMapTag(); + }); // <--[tag] // @attribute ]> @@ -109,23 +128,26 @@ public ObjectTag getObjectAttribute(Attribute attribute) { // If no effect is specified, returns whether the entity has any effect. // The effect type must be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html>. // --> - if (attribute.startsWith("has_effect")) { + PropertyParser.registerTag(ElementTag.class, "has_effect", (attribute, object) -> { boolean returnElement = false; if (attribute.hasParam()) { PotionEffectType effectType = PotionEffectType.getByName(attribute.getParam()); - for (org.bukkit.potion.PotionEffect effect : getEffectsList()) { - if (effect.getType().equals(effectType)) { - returnElement = true; - } + if (effectType == null) { + attribute.echoError("Invalid effect type specified: " + attribute.getParam()); + return null; + } + if (object.entity.isLivingEntity()) { + returnElement = object.entity.getLivingEntity().hasPotionEffect(effectType); + } + else if (object.isArrow()) { + returnElement = object.getArrow().hasCustomEffect(effectType); } } - else if (!getEffectsList().isEmpty()) { + else if (!object.getEffectsList().isEmpty()) { returnElement = true; } - return new ElementTag(returnElement).getObjectAttribute(attribute.fulfill(1)); - } - - return null; + return new ElementTag(returnElement); + }); } public void adjust(Mechanism mechanism) { @@ -136,28 +158,39 @@ public void adjust(Mechanism mechanism) { // @input ListTag // @description // Set the entity's active potion effects. - // Each item in the list is formatted as: TYPE,AMPLIFIER,DURATION,IS_AMBIENT,HAS_PARTICLES,HAS_ICON + // Each item in the list can be any of the following: + // 1: Comma-separated potion effect data in the format: TYPE,AMPLIFIER,DURATION,IS_AMBIENT,HAS_PARTICLES,HAS_ICON // Note that AMPLIFIER is a number representing the level, and DURATION is a number representing the time, in ticks, it will last for. // IS_AMBIENT, HAS_PARTICLES, and HAS_ICON are booleans. // For example: SPEED,0,120,false,true,true would give the entity a swiftness potion for 120 ticks. + // 2: A MapTag with "type", "amplifier", "duration", "ambient", "particles", and "icon" keys. + // For example: [type=SPEED;amplifier=0;duration=120t;ambient=false;particles=true;icon=true] // The effect type must be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html>. // @tags + // // // ]> // --> if (mechanism.matches("potion_effects")) { - ListTag effects = ListTag.valueOf(mechanism.getValue().asString(), mechanism.context); - for (String effectStr : effects) { - PotionEffect effect = ItemPotion.parseEffect(effectStr, mechanism.context); + for (ObjectTag effectObj : CoreUtilities.objectToList(mechanism.value, mechanism.context)) { + PotionEffect effect; + if (effectObj.canBeType(MapTag.class)) { + MapTag effectMap = effectObj.asType(MapTag.class, mechanism.context); + effect = ItemPotion.parseEffect(effectMap, mechanism.context); + } + else { + String effectStr = effectObj.toString(); + effect = ItemPotion.parseEffect(effectStr, mechanism.context); + } if (effect == null) { - mechanism.echoError("Invalid potion effect '" + effectStr + "'"); + mechanism.echoError("Invalid potion effect '" + effectObj + "'"); continue; } if (entity.isLivingEntity()) { entity.getLivingEntity().addPotionEffect(effect); } - else if (entity.getBukkitEntity() instanceof Arrow) { - ((Arrow) entity.getBukkitEntity()).addCustomEffect(effect, true); + else if (isArrow()) { + getArrow().addCustomEffect(effect, true); } } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemPotion.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemPotion.java index 94ed8ed57a..b0366e9f30 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemPotion.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemPotion.java @@ -1,15 +1,16 @@ package com.denizenscript.denizen.objects.properties.item; -import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.objects.ColorTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.utilities.debugging.Debug; +import com.denizenscript.denizencore.objects.core.DurationTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.objects.properties.Property; -import com.denizenscript.denizencore.tags.Attribute; +import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.denizenscript.denizencore.tags.TagContext; import com.denizenscript.denizencore.utilities.CoreUtilities; import org.bukkit.Material; @@ -19,14 +20,14 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionType; +import java.util.ArrayList; +import java.util.List; + public class ItemPotion implements Property { public static boolean describes(ObjectTag item) { return item instanceof ItemTag - && (((ItemTag) item).getBukkitMaterial() == Material.POTION - || ((ItemTag) item).getBukkitMaterial() == Material.SPLASH_POTION - || ((ItemTag) item).getBukkitMaterial() == Material.LINGERING_POTION - || ((ItemTag) item).getBukkitMaterial() == Material.TIPPED_ARROW); + && ((ItemTag) item).getItemMeta() instanceof PotionMeta; } public static ItemPotion getFrom(ObjectTag _item) { @@ -38,10 +39,6 @@ public static ItemPotion getFrom(ObjectTag _item) { } } - public static final String[] handledTags = new String[] { - "potion_base_type", "potion_base", "has_potion_effect", "potion_effect", "potion_effects" - }; - public static final String[] handledMechs = new String[] { "potion_effects" }; @@ -61,6 +58,34 @@ public static String stringifyEffect(PotionEffect effect) { effect.hasIcon(); } + public static MapTag effectToMap(PotionEffect effect) { + MapTag map = new MapTag(); + map.putObject("type", new ElementTag(effect.getType().getName())); + map.putObject("amplifier", new ElementTag(effect.getAmplifier())); + map.putObject("duration", new DurationTag((long) effect.getDuration())); + map.putObject("ambient", new ElementTag(effect.isAmbient())); + map.putObject("particles", new ElementTag(effect.hasParticles())); + map.putObject("icon", new ElementTag(effect.hasIcon())); + return map; + } + + public ListTag getMapTagData() { + ListTag result = new ListTag(); + MapTag base = new MapTag(); + PotionMeta meta = getMeta(); + base.putObject("type", new ElementTag(meta.getBasePotionData().getType().name())); + base.putObject("upgraded", new ElementTag(meta.getBasePotionData().isUpgraded())); + base.putObject("extended", new ElementTag(meta.getBasePotionData().isExtended())); + if (meta.hasColor()) { + base.putObject("color", new ColorTag(meta.getColor())); + } + result.addObject(base); + for (PotionEffect effect : meta.getCustomEffects()) { + result.addObject(effectToMap(effect)); + } + return result; + } + public static PotionEffect parseEffect(String str, TagContext context) { String[] d2 = str.split(","); PotionEffectType type; @@ -93,41 +118,95 @@ public static PotionEffect parseEffect(String str, TagContext context) { icon = check.asBoolean(); } } - return NMSHandler.getItemHelper().getPotionEffect(type, duration, amplifier, ambient, particles, icon); + return new PotionEffect(type, duration, amplifier, ambient, particles, icon); } - @Override - public String getPropertyString() { - if (!(item.getItemMeta() instanceof PotionMeta)) { + public static PotionEffect parseEffect(MapTag effectMap, TagContext context) { + PotionEffectType type; + DurationTag duration = new DurationTag(0); + int amplifier = 0; + boolean ambient = true; + boolean particles = true; + boolean icon = false; + if (effectMap.getObject("type") != null) { + String typeString = effectMap.getObject("type").toString(); + type = PotionEffectType.getByName(typeString); + if (type == null) { + if (context.showErrors()) { + Debug.echoError("Invalid potion effect type '" + typeString + "': effect type is required."); + } + return null; + } + } + else { + if (context.showErrors()) { + Debug.echoError("Invalid potion effect type: effect type is required."); + } return null; } - PotionMeta meta = (PotionMeta) item.getItemMeta(); - ListTag effects = new ListTag(); - effects.add(meta.getBasePotionData().getType() - + "," + meta.getBasePotionData().isUpgraded() - + "," + meta.getBasePotionData().isExtended() - + (meta.hasColor() ? "," + new ColorTag(meta.getColor()).identify().replace(",", "&comma") : "") - ); - for (PotionEffect pot : meta.getCustomEffects()) { - effects.add(stringifyEffect(pot)); + if (effectMap.getObject("amplifier") != null) { + ElementTag amplifierElement = effectMap.getObject("amplifier").asElement(); + if (amplifierElement.isInt()) { + amplifier = amplifierElement.asInt(); + } + else if (context.showErrors()) { + Debug.echoError("Invalid amplifier '" + amplifierElement + "': must be an integer."); + } } - return effects.identify(); + if (effectMap.getObject("duration") != null) { + ObjectTag durationObj = effectMap.getObject("duration"); + if (durationObj.canBeType(DurationTag.class)) { + duration = durationObj.asType(DurationTag.class, context); + } + else if (context.showErrors()) { + Debug.echoError("Invalid duration '" + durationObj + "': must be a valid DurationTag"); + } + } + if (effectMap.getObject("ambient") != null) { + ElementTag ambientElement = effectMap.getObject("ambient").asElement(); + if (ambientElement.isBoolean()) { + ambient = ambientElement.asBoolean(); + } + else if (context.showErrors()) { + Debug.echoError("Invalid ambient state '" + ambientElement + "': must be a boolean."); + } + } + if (effectMap.getObject("particles") != null) { + ElementTag particlesElement = effectMap.getObject("particles").asElement(); + if (particlesElement.isBoolean()) { + particles = particlesElement.asBoolean(); + } + else if (context.showErrors()) { + Debug.echoError("Invalid particles state '" + particlesElement + "': must be a boolean."); + } + } + if (effectMap.getObject("icon") != null) { + ElementTag iconElement = effectMap.getObject("icon").asElement(); + if (iconElement.isBoolean()) { + icon = iconElement.asBoolean(); + } + else if (context.showErrors()) { + Debug.echoError("Invalid icon state '" + iconElement + "': must be a boolean."); + } + } + return new PotionEffect(type, duration.getTicksAsInt(), amplifier, ambient, particles, icon); } - @Override - public String getPropertyId() { - return "potion_effects"; + public PotionMeta getMeta() { + return (PotionMeta) item.getItemMeta(); } @Override - public ObjectTag getObjectAttribute(Attribute attribute) { + public String getPropertyString() { + return getMapTagData().identify(); + } - if (attribute == null) { - return null; - } + @Override + public String getPropertyId() { + return "potion_effects"; + } - boolean has = item.getItemMeta() instanceof PotionMeta - && ((PotionMeta) item.getItemMeta()).hasCustomEffects(); + public static void registerTags() { // <--[tag] // @attribute @@ -138,10 +217,9 @@ public ObjectTag getObjectAttribute(Attribute attribute) { // Returns the base potion type name for this potion item. // The type will be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionType.html>. // --> - if (attribute.startsWith("potion_base_type") && item.getItemMeta() instanceof PotionMeta) { - PotionMeta meta = ((PotionMeta) item.getItemMeta()); - return new ElementTag(meta.getBasePotionData().getType().name()).getObjectAttribute(attribute.fulfill(1)); - } + PropertyParser.registerTag(ElementTag.class, "potion_base_type", (attribute, object) -> { + return new ElementTag(object.getMeta().getBasePotionData().getType().name()); + }); // <--[tag] // @attribute @@ -153,13 +231,12 @@ public ObjectTag getObjectAttribute(Attribute attribute) { // In the format Type,Level,Extended,Splash,Color // The type will be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionType.html>. // --> - if (attribute.startsWith("potion_base") && item.getItemMeta() instanceof PotionMeta) { - PotionMeta meta = ((PotionMeta) item.getItemMeta()); + PropertyParser.registerTag(ElementTag.class, "potion_base", (attribute, object) -> { + PotionMeta meta = object.getMeta(); return new ElementTag(meta.getBasePotionData().getType().name() + "," + (meta.getBasePotionData().isUpgraded() ? 2 : 1) - + "," + meta.getBasePotionData().isExtended() + "," + (item.getBukkitMaterial() == Material.SPLASH_POTION) - + (meta.hasColor() ? "," + new ColorTag(meta.getColor()).identify() : "") - ).getObjectAttribute(attribute.fulfill(1)); - } + + "," + meta.getBasePotionData().isExtended() + "," + (object.item.getBukkitMaterial() == Material.SPLASH_POTION) + + (meta.hasColor() ? "," + new ColorTag(meta.getColor()).identify() : "")); + }); // <--[tag] // @attribute @@ -170,14 +247,13 @@ public ObjectTag getObjectAttribute(Attribute attribute) { // Returns the list of potion effects on this item. // The effect type will be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html>. // --> - if (attribute.startsWith("potion_effects") && item.getItemMeta() instanceof PotionMeta) { + PropertyParser.registerTag(ListTag.class, "potion_effects", (attribute, object) -> { ListTag result = new ListTag(); - PotionMeta meta = ((PotionMeta) item.getItemMeta()); - for (PotionEffect pot : meta.getCustomEffects()) { + for (PotionEffect pot : object.getMeta().getCustomEffects()) { result.add(stringifyEffect(pot)); } - return result.getObjectAttribute(attribute.fulfill(1)); - } + return result; + }); // <--[tag] // @attribute @@ -186,162 +262,168 @@ public ObjectTag getObjectAttribute(Attribute attribute) { // @description // Returns whether the potion has a potion effect. // --> - if (attribute.startsWith("has_potion_effect")) { - return new ElementTag(has) - .getObjectAttribute(attribute.fulfill(1)); - } - - if (has) { - if (attribute.startsWith("potion_effect")) { - PotionMeta meta = ((PotionMeta) item.getItemMeta()); - - int potN = attribute.hasParam() ? attribute.getIntParam() - 1 : 0; - if (potN < 0 || potN > meta.getCustomEffects().size()) { - return null; - } - - attribute = attribute.fulfill(1); - - // <--[tag] - // @attribute ].is_splash> - // @returns ElementTag(Boolean) - // @mechanism ItemTag.potion_effects - // @group properties - // @description - // Returns whether the potion is a splash potion. - // --> - if (attribute.startsWith("is_splash")) { - return new ElementTag(item.getBukkitMaterial() == Material.SPLASH_POTION) - .getObjectAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ].is_extended> - // @returns ElementTag(Boolean) - // @mechanism ItemTag.potion_effects - // @group properties - // @description - // Returns whether the potion effect is extended. - // --> - if (attribute.startsWith("is_extended")) { - return new ElementTag(meta.getBasePotionData().isExtended()) - .getObjectAttribute(attribute.fulfill(1)); - } + PropertyParser.registerTag(ElementTag.class, "has_potion_effect", (attribute, object) -> { + return new ElementTag(object.getMeta().hasCustomEffects()); + }); + + PropertyParser.registerTag(ElementTag.class, "potion_effect", (attribute, object) -> { + PotionMeta meta = object.getMeta(); + int potN = attribute.hasParam() ? attribute.getIntParam() - 1 : 0; + if (potN < 0 || potN > meta.getCustomEffects().size()) { + return null; + } + + // <--[tag] + // @attribute ].is_splash> + // @returns ElementTag(Boolean) + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns whether the potion is a splash potion. + // --> + if (attribute.startsWith("is_splash", 2)) { + attribute.fulfill(1); + return new ElementTag(object.item.getBukkitMaterial() == Material.SPLASH_POTION); + } - // <--[tag] - // @attribute ].level> - // @returns ElementTag(Number) - // @mechanism ItemTag.potion_effects - // @group properties - // @description - // Returns the potion effect's level. - // --> - if (attribute.startsWith("level")) { - return new ElementTag(meta.getBasePotionData().isUpgraded() ? 2 : 1) - .getObjectAttribute(attribute.fulfill(1)); - } + // <--[tag] + // @attribute ].is_extended> + // @returns ElementTag(Boolean) + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns whether the potion effect is extended. + // --> + if (attribute.startsWith("is_extended", 2)) { + attribute.fulfill(1); + return new ElementTag(meta.getBasePotionData().isExtended()); + } - // <--[tag] - // @attribute ].is_ambient> - // @returns ElementTag(Boolean) - // @mechanism ItemTag.potion_effects - // @group properties - // @description - // Returns whether the potion effect is ambient. - // "Ambient" effects in vanilla came from a beacon, while non-ambient came from a potion. - // --> - if (attribute.startsWith("is_ambient")) { - return new ElementTag(meta.getCustomEffects().get(potN).isAmbient()) - .getObjectAttribute(attribute.fulfill(1)); - } + // <--[tag] + // @attribute ].level> + // @returns ElementTag(Number) + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns the potion effect's level. + // --> + if (attribute.startsWith("level", 2)) { + attribute.fulfill(1); + return new ElementTag(meta.getBasePotionData().isUpgraded() ? 2 : 1); + } - // <--[tag] - // @attribute ].icon> - // @returns ElementTag(Boolean) - // @mechanism ItemTag.potion_effects - // @group properties - // @description - // Returns whether the potion effect shows an icon. - // --> - if (attribute.startsWith("icon")) { - return new ElementTag(meta.getCustomEffects().get(potN).hasIcon()).getObjectAttribute(attribute.fulfill(1)); - } + // <--[tag] + // @attribute ].is_ambient> + // @returns ElementTag(Boolean) + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns whether the potion effect is ambient. + // "Ambient" effects in vanilla came from a beacon, while non-ambient came from a potion. + // --> + if (attribute.startsWith("is_ambient", 2)) { + attribute.fulfill(1); + return new ElementTag(meta.getCustomEffects().get(potN).isAmbient()); + } - // <--[tag] - // @attribute ].has_particles> - // @returns ElementTag(Boolean) - // @mechanism ItemTag.potion_effects - // @group properties - // @description - // Returns whether the potion effect has particles. - // --> - if (attribute.startsWith("has_particles")) { - return new ElementTag(meta.getCustomEffects().get(potN).hasParticles()) - .getObjectAttribute(attribute.fulfill(1)); - } + // <--[tag] + // @attribute ].icon> + // @returns ElementTag(Boolean) + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns whether the potion effect shows an icon. + // --> + if (attribute.startsWith("icon", 2)) { + attribute.fulfill(1); + return new ElementTag(meta.getCustomEffects().get(potN).hasIcon()); + } - // <--[tag] - // @attribute ].duration> - // @returns ElementTag(Number) - // @mechanism ItemTag.potion_effects - // @group properties - // @description - // Returns the duration in ticks of the potion. - // --> - if (attribute.startsWith("duration")) { - return new ElementTag(meta.getCustomEffects().get(potN).getDuration()) - .getObjectAttribute(attribute.fulfill(1)); - } + // <--[tag] + // @attribute ].has_particles> + // @returns ElementTag(Boolean) + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns whether the potion effect has particles. + // --> + if (attribute.startsWith("has_particles", 2)) { + attribute.fulfill(1); + return new ElementTag(meta.getCustomEffects().get(potN).hasParticles()); + } - // <--[tag] - // @attribute ].amplifier> - // @returns ElementTag(Number) - // @mechanism ItemTag.potion_effects - // @group properties - // @description - // Returns the amplifier level of the potion effect. - // --> - if (attribute.startsWith("amplifier")) { - return new ElementTag(meta.getCustomEffects().get(potN).getAmplifier()) - .getObjectAttribute(attribute.fulfill(1)); - } + // <--[tag] + // @attribute ].duration> + // @returns ElementTag(Number) + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns the duration in ticks of the potion. + // --> + if (attribute.startsWith("duration", 2)) { + attribute.fulfill(1); + return new ElementTag(meta.getCustomEffects().get(potN).getDuration()); + } - // <--[tag] - // @attribute ].type> - // @returns ElementTag - // @mechanism ItemTag.potion_effects - // @group properties - // @description - // Returns the type of the potion effect. - // The effect type will be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html>. - // --> - if (attribute.startsWith("type")) { - return new ElementTag(meta.getCustomEffects().get(potN).getType().getName()) - .getObjectAttribute(attribute.fulfill(1)); - } + // <--[tag] + // @attribute ].amplifier> + // @returns ElementTag(Number) + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns the amplifier level of the potion effect. + // --> + if (attribute.startsWith("amplifier", 2)) { + attribute.fulfill(1); + return new ElementTag(meta.getCustomEffects().get(potN).getAmplifier()); + } - if (attribute.startsWith("data")) { - return new ElementTag(0) - .getObjectAttribute(attribute.fulfill(1)); - } + // <--[tag] + // @attribute ].type> + // @returns ElementTag + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns the type of the potion effect. + // The effect type will be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html>. + // --> + if (attribute.startsWith("type", 2)) { + attribute.fulfill(1); + return new ElementTag(meta.getCustomEffects().get(potN).getType().getName()); + } - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @mechanism ItemTag.potion_effects - // @group properties - // @warning Don't use this directly, use its sub-tags! - // @description - // Returns the potion effect on this item. - // In the format Effect,Level,Extended,Splash - // --> - return new ElementTag(meta.getBasePotionData().getType().name() + "," + (meta.getBasePotionData().isUpgraded() ? 2 : 1) - + "," + meta.getBasePotionData().isExtended() + "," + (item.getBukkitMaterial() == Material.SPLASH_POTION)) - .getObjectAttribute(attribute); + if (attribute.startsWith("data", 2)) { + attribute.fulfill(1); + return new ElementTag(0); } - } - return null; + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @mechanism ItemTag.potion_effects + // @group properties + // @warning Don't use this directly, use its sub-tags! + // @description + // Returns the potion effect on this item. + // In the format Effect,Level,Extended,Splash + // --> + PotionData data = meta.getBasePotionData(); + return new ElementTag(data.getType().name() + "," + (data.isUpgraded() ? 2 : 1) + + "," + data.isExtended() + "," + (object.item.getBukkitMaterial() == Material.SPLASH_POTION)); + + }); + + // <--[tag] + // @attribute + // @returns ListTag(MapTag) + // @mechanism ItemTag.potion_effects + // @group properties + // @description + // Returns a list of all potion effects on this item, in the MapTag format of the mechanism. + // --> + PropertyParser.registerTag(ListTag.class, "effects_data", (attribute, object) -> { + return object.getMapTagData(); + }); } @Override @@ -353,13 +435,21 @@ public void adjust(Mechanism mechanism) { // @input ListTag // @description // Sets the potion's potion effect(s). - // Input is a formed like: Type,Upgraded,Extended(,Color)|Effect,Amplifier,Duration,Ambient,Particles,Icon|... - // For example: SPEED,true,false|SPEED,2,200,false,true,true - // Second example: REGEN,false,true,RED|REGENERATION,1,500,true,false,false + // The first item in the list must be either: + // 1: Comma-separated base potion data, in the format Type,Upgraded,Extended(,Color). + // For example: "SPEED,true,false", or "REGEN,false,true,RED". // Color can also be used like "255&comma128&comma0" (r,g,b but replace ',' with '&comma'). + // 2: A MapTag with "type", "upgraded" and "extended" keys, and an optional "color" key. + // For example: [type=SPEED;upgraded=true;extended=false;color=RED]. + // The following items in the list are potion effects, which must be either: + // 1: Comma-separated potion effect data, in the format Effect,Amplifier,Duration,Ambient,Particles,Icon. + // For example: SPEED,2,200,false,true,true. + // 2: A MapTag with "type", "amplifier", "duration", "ambient", "particles" and "icon" keys. + // For example: [type=SPEED;amplifier=2;duration=200t;ambient=false;particles=true;icon=true]. // The primary type must be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionType.html>. // The effect type must be from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html>. // @tags + // // ]> // ].type> // ].duration> @@ -371,47 +461,107 @@ public void adjust(Mechanism mechanism) { // // --> if (mechanism.matches("potion_effects")) { - ListTag data = mechanism.valueAsType(ListTag.class); - String[] d1 = data.get(0).split(","); - PotionMeta meta = (PotionMeta) item.getItemMeta(); + List data = new ArrayList<>(CoreUtilities.objectToList(mechanism.value, mechanism.context)); + ObjectTag firstObj = data.remove(0); + PotionMeta meta = getMeta(); PotionType type; - try { - type = PotionType.valueOf(d1[0].toUpperCase()); + boolean upgraded = false; + boolean extended = false; + ColorTag color = null; + if (firstObj.canBeType(MapTag.class)) { + MapTag baseEffect = firstObj.asType(MapTag.class, mechanism.context); + if (baseEffect.getObject("type") != null) { + ElementTag typeElement = baseEffect.getObject("type").asElement(); + if (!typeElement.matchesEnum(PotionType.class)) { + mechanism.echoError("Invalid base potion type '" + typeElement + "': type is required"); + return; + } + type = PotionType.valueOf(typeElement.asString().toUpperCase()); + } + else { + mechanism.echoError("No base potion type specified: type is required"); + return; + } + if (baseEffect.getObject("upgraded") != null) { + ElementTag upgradedElement = baseEffect.getObject("upgraded").asElement(); + if (upgradedElement.isBoolean()) { + upgraded = upgradedElement.asBoolean(); + } + else { + mechanism.echoError("Invalid upgraded state '" + upgradedElement + "': must be a boolean"); + } + } + if (baseEffect.getObject("extended") != null) { + ElementTag extendedElement = baseEffect.getObject("extended").asElement(); + if (extendedElement.isBoolean()) { + extended = extendedElement.asBoolean(); + } + else { + mechanism.echoError("Invalid extended state '" + extendedElement + "': must be a boolean"); + } + } + if (baseEffect.getObject("color") != null) { + ObjectTag colorObj = baseEffect.getObject("color"); + if (colorObj.canBeType(ColorTag.class)) { + color = colorObj.asType(ColorTag.class, mechanism.context); + } + else { + mechanism.echoError("Invalid color '" + colorObj + "': must be a valid ColorTag"); + } + } } - catch (IllegalArgumentException ex) { - mechanism.echoError("Invalid potion type name '" + d1[0] + "'"); - return; + else { + String[] d1 = firstObj.toString().split(","); + try { + type = PotionType.valueOf(d1[0].toUpperCase()); + } + catch (IllegalArgumentException ex) { + mechanism.echoError("Invalid base potion type '" + d1[0] + "': type is required"); + return; + } + upgraded = CoreUtilities.equalsIgnoreCase(d1[1], "true"); + extended = CoreUtilities.equalsIgnoreCase(d1[2], "true"); + if (d1.length > 3) { + ColorTag temp = ColorTag.valueOf(d1[3].replace("&comma", ","), mechanism.context); + if (temp == null) { + mechanism.echoError("Invalid color '" + d1[3] + "': must be a valid ColorTag"); + } + else { + color = temp; + } + } } - boolean upgraded = CoreUtilities.equalsIgnoreCase(d1[1], "true"); - boolean extended = CoreUtilities.equalsIgnoreCase(d1[2], "true"); if (upgraded && !type.isUpgradeable()) { mechanism.echoError("Cannot upgrade potion of type '" + type.name() + "'"); upgraded = false; } if (extended && !type.isExtendable()) { mechanism.echoError("Cannot extend potion of type '" + type.name() + "'"); - upgraded = false; + extended = false; } if (upgraded && extended) { mechanism.echoError("Cannot both upgrade and extend a potion"); extended = false; } - meta.setBasePotionData(new PotionData(type, extended, upgraded)); - if (d1.length > 3) { - ColorTag color = ColorTag.valueOf(d1[3].replace("&comma", ","), mechanism.context); - if (color == null) { - mechanism.echoError("Invalid ColorTag input '" + d1[3] + "'"); - } + if (color != null) { meta.setColor(color.getColor()); } + meta.setBasePotionData(new PotionData(type, extended, upgraded)); meta.clearCustomEffects(); - for (int i = 1; i < data.size(); i++) { - PotionEffect effect = parseEffect(data.get(i), mechanism.context); - if (effect == null) { - mechanism.echoError("Invalid potion effect '" + data.get(i) + "'"); - continue; + for (ObjectTag effectObj : data) { + PotionEffect effect; + if (effectObj.canBeType(MapTag.class)) { + effect = parseEffect(effectObj.asType(MapTag.class, mechanism.context), mechanism.context); + } + else { + effect = parseEffect(effectObj.toString(), mechanism.context); + } + if (effect != null) { + meta.addCustomEffect(effect, false); + } + else { + mechanism.echoError("Invalid potion effect '" + effectObj + "'"); } - meta.addCustomEffect(effect, false); } item.setItemMeta(meta); } diff --git a/v1_16/src/main/java/com/denizenscript/denizen/nms/v1_16/helpers/ItemHelperImpl.java b/v1_16/src/main/java/com/denizenscript/denizen/nms/v1_16/helpers/ItemHelperImpl.java index bd7b65edea..0043bf5a89 100644 --- a/v1_16/src/main/java/com/denizenscript/denizen/nms/v1_16/helpers/ItemHelperImpl.java +++ b/v1_16/src/main/java/com/denizenscript/denizen/nms/v1_16/helpers/ItemHelperImpl.java @@ -31,8 +31,6 @@ import org.bukkit.inventory.Recipe; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; import java.util.*; @@ -255,11 +253,6 @@ public ItemStack setNbtData(ItemStack itemStack, CompoundTag compoundTag) { return CraftItemStack.asBukkitCopy(nmsItemStack); } - @Override - public PotionEffect getPotionEffect(PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon) { - return new PotionEffect(type, duration, amplifier, ambient, particles, icon); - } - @Override public void setInventoryItem(Inventory inventory, ItemStack item, int slot) { if (inventory instanceof CraftInventoryPlayer && ((CraftInventoryPlayer) inventory).getInventory().player == null) { diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java index ce5239ef4d..ab520c4e21 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java @@ -52,8 +52,6 @@ import org.bukkit.inventory.Recipe; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; import java.util.*; @@ -276,11 +274,6 @@ public ItemStack setNbtData(ItemStack itemStack, CompoundTag compoundTag) { return CraftItemStack.asBukkitCopy(nmsItemStack); } - @Override - public PotionEffect getPotionEffect(PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon) { - return new PotionEffect(type, duration, amplifier, ambient, particles, icon); - } - @Override public void setInventoryItem(Inventory inventory, ItemStack item, int slot) { if (inventory instanceof CraftInventoryPlayer && ((CraftInventoryPlayer) inventory).getInventory().player == null) { diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/ItemHelperImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/ItemHelperImpl.java index 261a15f2d2..11fc0c561c 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/ItemHelperImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/ItemHelperImpl.java @@ -52,8 +52,6 @@ import org.bukkit.inventory.Recipe; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; import java.lang.reflect.Field; import java.util.*; @@ -297,11 +295,6 @@ public ItemStack setNbtData(ItemStack itemStack, CompoundTag compoundTag) { return CraftItemStack.asBukkitCopy(nmsItemStack); } - @Override - public PotionEffect getPotionEffect(PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon) { - return new PotionEffect(type, duration, amplifier, ambient, particles, icon); - } - @Override public void setInventoryItem(Inventory inventory, ItemStack item, int slot) { if (inventory instanceof CraftInventoryPlayer && ((CraftInventoryPlayer) inventory).getInventory().player == null) {