From 9adc6430f4572dc0ceca80c89d6442681ab11f0f Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Wed, 8 Jan 2025 22:31:50 +0000 Subject: [PATCH] 1.20+ potions support (#2692) * Split base potion data handling for cleaner flow * Custom name, null base type, modern effect type * Back-Support legacy tags/mechs * Metaify all changes * Fixup some version checks * Minor `applyBasePotionData` cleanup & renames * More backsupport for now-null base potion type * Final fixups * `effect` key only on 1.20+ to match input * Oops whitespace --- paper/pom.xml | 2 +- .../events/PlayerBeaconEffectScriptEvent.java | 4 +- .../paper/utilities/PaperAPIToolsImpl.java | 6 + .../entity/EntityPotionEffectScriptEvent.java | 8 +- .../objects/properties/PropertyRegistry.java | 4 +- .../entity/EntityPotionEffects.java | 20 +- .../objects/properties/item/ItemPotion.java | 200 ++++++++++++------ .../utilities/BukkitImplDeprecations.java | 3 + .../denizen/utilities/PaperAPITools.java | 6 + 9 files changed, 161 insertions(+), 92 deletions(-) diff --git a/paper/pom.xml b/paper/pom.xml index 415da04a99..2ea638249e 100644 --- a/paper/pom.xml +++ b/paper/pom.xml @@ -25,7 +25,7 @@ io.papermc.paper paper-api - 1.21.3-R0.1-SNAPSHOT + 1.21.4-R0.1-SNAPSHOT provided diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerBeaconEffectScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerBeaconEffectScriptEvent.java index 6f204e60e6..99baed8d42 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerBeaconEffectScriptEvent.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerBeaconEffectScriptEvent.java @@ -31,7 +31,7 @@ public class PlayerBeaconEffectScriptEvent extends BukkitScriptEvent implements // // @Context // returns the LocationTag of the beacon applying an effect. - // returns a MapTag of the potion effect (in the same format as <@link tag EntityTag.effects_data>). + // returns a MapTag of the potion effect in <@link language Potion Effect Format>. // returns an ElementTag of the effect type. // returns an ElementTag(Boolean) of whether the beacon effect is the primary effect. // @@ -78,7 +78,7 @@ public ObjectTag getContext(String name) { return switch (name) { case "location" -> new LocationTag(event.getBlock().getLocation()); case "effect" -> new ElementTag(ItemPotion.effectToLegacyString(event.getEffect(), null)); - case "effect_data" -> ItemPotion.effectToMap(event.getEffect()); + case "effect_data" -> ItemPotion.effectToMap(event.getEffect(), true); case "effect_type" -> new ElementTag(event.getEffect().getType().getName()); case "is_primary" -> new ElementTag(event.isPrimary()); default -> super.getContext(name); diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index 54ce299a36..d6499b8c1e 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -35,6 +35,7 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.*; +import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.potion.PotionBrewer; import org.bukkit.scoreboard.Team; import org.bukkit.util.Consumer; @@ -387,4 +388,9 @@ public String getClientBrand(Player player) { public boolean canUseEquipmentSlot(LivingEntity entity, EquipmentSlot slot) { return NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) ? entity.canUseEquipmentSlot(slot) : super.canUseEquipmentSlot(entity, slot); } + + @Override + public boolean hasCustomName(PotionMeta meta) { + return meta.hasCustomPotionName(); + } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityPotionEffectScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityPotionEffectScriptEvent.java index 531adc9734..1ec33c7c3e 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityPotionEffectScriptEvent.java +++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityPotionEffectScriptEvent.java @@ -34,8 +34,8 @@ public class EntityPotionEffectScriptEvent extends BukkitScriptEvent implements // returns the cause of the effect change, based on <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/entity/EntityPotionEffectEvent.Cause.html> // returns the action of the effect changed, which can be 'added', 'changed', 'cleared', or 'removed' // returns whether the new potion effect will override the old. - // returns the new potion effect (in the same format as <@link tag EntityTag.effects_data>) (if any). - // returns the old potion effect (in the same format as <@link tag EntityTag.effects_data>) (if any). + // returns the new potion effect in <@link language Potion Effect Format>. + // returns the old potion effect in <@link language Potion Effect Format>. // returns the name of the modified potion effect type. // // @Determine @@ -118,8 +118,8 @@ public ObjectTag getContext(String name) { case "override" -> new ElementTag(event.isOverride()); case "new_effect" -> event.getNewEffect() == null ? null : new ElementTag(ItemPotion.effectToLegacyString(event.getNewEffect(), null)); case "old_effect" -> event.getOldEffect() == null ? null : new ElementTag(ItemPotion.effectToLegacyString(event.getOldEffect(), null)); - case "new_effect_data" -> event.getNewEffect() == null ? null : ItemPotion.effectToMap(event.getNewEffect()); - case "old_effect_data" -> event.getOldEffect() == null ? null : ItemPotion.effectToMap(event.getOldEffect()); + case "new_effect_data" -> event.getNewEffect() == null ? null : ItemPotion.effectToMap(event.getNewEffect(), true); + case "old_effect_data" -> event.getOldEffect() == null ? null : ItemPotion.effectToMap(event.getOldEffect(), true); default -> super.getContext(name); }; } diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/PropertyRegistry.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/PropertyRegistry.java index 6e6306bb9b..a3e5a7c6a6 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/PropertyRegistry.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/PropertyRegistry.java @@ -244,9 +244,7 @@ public static void registerMainProperties() { registerItemProperty(ItemMap.class, "map_id"); PropertyParser.registerProperty(ItemNBT.class, ItemTag.class); registerItemProperty(ItemPatterns.class, "banner_patterns"); - if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19)) { - registerItemProperty(ItemPotion.class, "potion_contents"); - } + registerItemProperty(ItemPotion.class, "potion_contents"); PropertyParser.registerProperty(ItemQuantity.class, ItemTag.class); PropertyParser.registerProperty(ItemRawNBT.class, ItemTag.class); registerItemProperty(ItemRepairCost.class, "repair_cost"); 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 eddc57814a..8b7f1c08e5 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 @@ -66,10 +66,10 @@ public ListTag getEffectsListTag(TagContext context) { return result; } - public ListTag getEffectsMapTag() { + public ListTag getEffectsMapTag(boolean includeDeprecated) { ListTag result = new ListTag(); for (PotionEffect effect : getEffectsList()) { - result.addObject(ItemPotion.effectToMap(effect)); + result.addObject(ItemPotion.effectToMap(effect, includeDeprecated)); } return result; } @@ -83,7 +83,7 @@ public Arrow getArrow() { } public String getPropertyString() { - ListTag effects = getEffectsMapTag(); + ListTag effects = getEffectsMapTag(false); return effects.isEmpty() ? null : effects.identify(); } @@ -114,10 +114,10 @@ public static void register() { // @group attribute // @mechanism EntityTag.potion_effects // @description - // Returns the active potion effects on the entity, in the MapTag format of the mechanism. + // Returns the active potion effects on the entity, as a list of maps in <@link language Potion Effect Format>. // --> PropertyParser.registerTag(EntityPotionEffects.class, ListTag.class, "effects_data", (attribute, object) -> { - return object.getEffectsMapTag(); + return object.getEffectsMapTag(true); }); // <--[tag] @@ -160,17 +160,9 @@ public void adjust(Mechanism mechanism) { // @input ListTag // @description // Set the entity's active potion effects. - // Each item in the list must be a MapTag with keys: - // "type" - from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html> - // "amplifier" - number to increase the level by (0 for default level 1) - // "duration" - DurationTag, how long it lasts - // "ambient", "particles", "icon" - booleans - // - // For example: [type=SPEED;amplifier=0;duration=120t;ambient=false;particles=true;icon=true] - // This example would be a level 1 swiftness potion that lasts 120 ticks. + // Each item in the list must be a MapTag in <@link language Potion Effect Format>. // @tags // - // // ]> // --> if (mechanism.matches("potion_effects")) { 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 93bbed2f03..6aa445a123 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 @@ -5,6 +5,7 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.properties.bukkit.BukkitColorExtensions; import com.denizenscript.denizen.utilities.BukkitImplDeprecations; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.ObjectTag; @@ -26,21 +27,44 @@ import java.util.ArrayList; import java.util.List; -// TODO: 1.20.6: Spigot removed the PotionData API, can either remove relevant features on 1.20.6, or try and backsupport somehow (probably either hard-coding our own data or hacking it based on the name) public class ItemPotion extends ItemProperty { + // <--[language] + // @name Potion Effect Format + // @group Minecraft Logic + // @description + // Potion effects (be it on an entity, given by a potion, etc.) are represented in Denizen as <@link ObjectType MapTag>s with the following keys: + // - effect: the effect type given by the effect, see <@link url https://minecraft.wiki/w/Effect#Descriptions>. + // - amplifier: the number to increase the effect level by, usually controls how powerful its effects are (optional for input, defaults to 0 which is level 1). + // - duration (<@link ObjectType DurationTag>): how long the effect should last (optional for input, defaults to 0s). + // - ambient: a boolean (true/false) for whether the effect's particles should be more translucent and less intrusive, like effects given by a beacon (optional for input, defaults to true). + // - particles: a boolean (true/false) for whether the effect should display particles (optional for input, defaults to true). + // - icon: a boolean (true/false) for whether the effect should have an icon on a player's HUD when applied (optional for input, defaults to false). + // + // For example, [effect=speed;amplifier=2;duration=10s;ambient=false;particles=true;icon=true] would be a level 3 speed effect that lasts 10 seconds, with (normal) particles and an icon. + // --> + public static boolean describes(ItemTag item) { return item.getItemMeta() instanceof PotionMeta || item.getItemMeta() instanceof SuspiciousStewMeta; } - public static MapTag effectToMap(PotionEffect effect) { + public static MapTag effectToMap(PotionEffect effect, boolean includeDeprecated) { MapTag map = new MapTag(); - map.putObject("type", new ElementTag(effect.getType().getName())); + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { + map.putObject("effect", new ElementTag(Utilities.namespacedKeyToString(effect.getType().getKey()), true)); + } + else { + includeDeprecated = true; + } 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())); + // TODO: deprecate this + if (includeDeprecated) { + map.putObject("type", new ElementTag(effect.getType().getName(), true)); + } return map; } @@ -50,15 +74,21 @@ public ListTag getMapTagData(boolean includeExtras) { if (getItemMeta() instanceof PotionMeta potionMeta) { MapTag base = new MapTag(); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { - base.putObject("base_type", new ElementTag(Utilities.namespacedKeyToString(potionMeta.getBasePotionType().getKey()), true)); + if (potionMeta.hasBasePotionType()) { + base.putObject("base_type", new ElementTag(Utilities.namespacedKeyToString(potionMeta.getBasePotionType().getKey()), true)); + } + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && PaperAPITools.instance.hasCustomName(potionMeta)) { + base.putObject("translation_id", new ElementTag(potionMeta.getCustomName(), true)); + } } else { includeExtras = true; } if (includeExtras) { // TODO: Eventually remove these 4 - base.putObject("type", new ElementTag(potionMeta.getBasePotionData().getType())); - base.putObject("upgraded", new ElementTag(potionMeta.getBasePotionData().isUpgraded())); - base.putObject("extended", new ElementTag(potionMeta.getBasePotionData().isExtended())); + LegacyPotionData data = getLegacyBasePotionData(); + base.putObject("type", new ElementTag(data.type(), true)); + base.putObject("upgraded", new ElementTag(data.upgraded())); + base.putObject("extended", new ElementTag(data.extended())); if (potionMeta.hasColor()) { base.putObject("color", BukkitColorExtensions.fromColor(potionMeta.getColor())); } @@ -66,7 +96,7 @@ public ListTag getMapTagData(boolean includeExtras) { result.addObject(base); } for (PotionEffect potionEffect : potionEffects) { - result.addObject(effectToMap(potionEffect)); + result.addObject(effectToMap(potionEffect, includeExtras)); } return result; } @@ -78,19 +108,26 @@ public static PotionEffect parseEffect(MapTag effectMap, TagContext context) { boolean ambient = true; boolean particles = true; boolean icon = false; - if (effectMap.containsKey("type")) { - 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; + ElementTag effectInput = effectMap.getElement("effect"); + ElementTag typeInput = null; + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && effectInput != null) { + type = Registry.EFFECT.get(Utilities.parseNamespacedKey(effectInput.asString())); + } + else if ((typeInput = effectMap.getElement("type")) != null) { + type = PotionEffectType.getByName(typeInput.asString()); + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { + BukkitImplDeprecations.oldPotionEffectType.warn(context); } } else { if (context.showErrors()) { - Debug.echoError("Invalid potion effect type: effect type is required."); + Debug.echoError("Invalid potion effect: effect type is required."); + } + return null; + } + if (type == null) { + if (context.showErrors()) { + Debug.echoError("Invalid potion effect type '" + (effectInput != null ? effectInput : typeInput) + "' specified: effect type is required."); } return null; } @@ -154,32 +191,39 @@ public ListTag getPropertyValue() { return getMapTagData(false); } + private boolean applyBasePotionData(PotionMeta potionMeta, ObjectTag baseData, Mechanism mechanism) { + if (!baseData.canBeType(MapTag.class)) { + return applyLegacyStringBasePotionData(baseData.toString(), potionMeta, mechanism); + } + MapTag baseDataMap = baseData.asType(MapTag.class, mechanism.context); + if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19) || baseDataMap.containsKey("type")) { + return applyLegacyMapBasePotionData(baseDataMap, potionMeta, mechanism); + } + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { + ElementTag translationId = baseDataMap.getElement("translation_id"); + potionMeta.setCustomName(translationId != null ? translationId.asString() : null); + } + ElementTag baseTypeElement = baseDataMap.getElement("base_type"); + if (baseTypeElement == null) { + potionMeta.setBasePotionType(null); + return false; + } + PotionType baseType = Utilities.elementToEnumlike(baseTypeElement, PotionType.class); + if (baseType == null) { + mechanism.echoError("Invalid base potion type '" + baseTypeElement + "' specified."); + return true; + } + potionMeta.setBasePotionType(baseType); + return false; + } + @Override public void setPropertyValue(ObjectTag value, Mechanism mechanism) { List data = new ArrayList<>(CoreUtilities.objectToList(value, mechanism.context)); ItemMeta meta = getItemMeta(); if (meta instanceof PotionMeta potionMeta) { - ObjectTag firstObj = data.remove(0); - if (firstObj.canBeType(MapTag.class)) { - MapTag baseEffect = firstObj.asType(MapTag.class, mechanism.context); - if (baseEffect.containsKey("base_type")) { - ElementTag baseTypeElement = baseEffect.getElement("base_type"); - PotionType type = Registry.POTION.get(Utilities.parseNamespacedKey(baseTypeElement.asString())); - if (type == null && baseTypeElement.matchesEnum(PotionType.class)) { - type = baseTypeElement.asEnum(PotionType.class); - } - if (type == null) { - mechanism.echoError("Invalid base potion type '" + baseTypeElement + "': valid base potion_type is required"); - return; - } - potionMeta.setBasePotionType(type); - } - else { - applyLegacyMapBasePotionData(baseEffect, potionMeta, mechanism); - } - } - else { - applyLegacyStringBasePotionData(firstObj.toString(), potionMeta, mechanism); + if (applyBasePotionData(potionMeta, data.remove(0), mechanism)) { + return; } potionMeta.clearCustomEffects(); } @@ -224,7 +268,7 @@ public static void register() { // Returns a list of all potion effects on this item, in the same format as the MapTag input to the mechanism. // This applies to Potion items, Tipped Arrow items, and Suspicious Stews. // Note that for potions or tipped arrows (not suspicious stew) the first value in the list is the potion's base type. - // All subsequent entries are effect data. + // All subsequent entries are potion effects in <@link language Potion Effect Format>. // --> PropertyParser.registerTag(ItemPotion.class, ListTag.class, "effects_data", (attribute, prop) -> { return prop.getMapTagData(true); @@ -239,22 +283,16 @@ public static void register() { // This applies to Potion items, Tipped Arrow items, and Suspicious Stews. // // For potions or tipped arrows (not suspicious stew), the first item in the list must be a MapTag with keys: - // "base_type" - from <@link url https://minecraft.wiki/w/Potion#Item_data> + // "base_type" - from <@link url https://minecraft.wiki/w/Potion#Item_data> (optional, becomes an uncraftable potion when unset). + // "translation_id" - controls the translation key used for the default item display name. The translation key used is "item.minecraft..effect." (optional). // // For example: [base_type=strong_swiftness] // This example produces an item labeled as "Potion of Swiftness - Speed II (1:30)" // - // Each following item in the list are potion effects, which must be a MapTag with keys: - // "type" - from <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html> - // "amplifier" - number to increase the level by (0 for default level 1) (optional, default 0) - // "duration" - DurationTag, how long it lasts (optional, default 0s) - // "ambient", "particles", "icon" - booleans (optional, default true, true, false) - // - // For example: [type=SPEED;amplifier=2;duration=10s;ambient=false;particles=true;icon=true] - // This example would be a level 3 swiftness potion that lasts 10 seconds. + // Each following item in the list are potion effects, which must be a MapTag in <@link language Potion Effect Format>. // // A very short full default potion item would be: potion[potion_effects=[base_type=regeneration] - // A (relatively) short full potion item would be: potion[potion_effects=] + // A (relatively) short full potion item would be: potion[potion_effects=] // (Note the list constructor to force data format interpretation, as potion formats can be given multiple ways and the system will get confused without a constructor) // // @tags @@ -293,12 +331,12 @@ public static void register() { // Deprecated in favor of <@link tag ItemTag.effects_data> // --> PropertyParser.registerTag(ItemPotion.class, ElementTag.class, "potion_base_type", (attribute, object) -> { - if (!(object.getItemMeta() instanceof PotionMeta potionMeta)) { + if (!(object.getItemMeta() instanceof PotionMeta)) { attribute.echoError("This item does not have a base potion type."); return null; } BukkitImplDeprecations.oldPotionEffects.warn(attribute.context); - return new ElementTag(potionMeta.getBasePotionData().getType()); + return new ElementTag(object.getLegacyBasePotionData().type(), true); }); // <--[tag] @@ -316,8 +354,9 @@ public static void register() { return null; } BukkitImplDeprecations.oldPotionEffects.warn(attribute.context); - return new ElementTag(potionMeta.getBasePotionData().getType().name() + "," + (potionMeta.getBasePotionData().isUpgraded() ? 2 : 1) - + "," + potionMeta.getBasePotionData().isExtended() + "," + (object.getMaterial() == Material.SPLASH_POTION) + LegacyPotionData data = object.getLegacyBasePotionData(); + return new ElementTag(data.type() + "," + (data.upgraded() ? 2 : 1) + + "," + data.extended() + "," + (object.getMaterial() == Material.SPLASH_POTION) + (potionMeta.hasColor() ? "," + BukkitColorExtensions.fromColor(potionMeta.getColor()).identify() : "")); }); @@ -359,17 +398,17 @@ public static void register() { } if (attribute.startsWith("is_extended", 2)) { attribute.fulfill(1); - if (!(object.getItemMeta() instanceof PotionMeta potionMeta)) { + if (!(object.getItemMeta() instanceof PotionMeta)) { return null; } - return new ElementTag(potionMeta.getBasePotionData().isExtended()); + return new ElementTag(object.getLegacyBasePotionData().extended()); } if (attribute.startsWith("level", 2)) { attribute.fulfill(1); - if (!(object.getItemMeta() instanceof PotionMeta potionMeta)) { + if (!(object.getItemMeta() instanceof PotionMeta)) { return null; } - return new ElementTag(potionMeta.getBasePotionData().isUpgraded() ? 2 : 1); + return new ElementTag(object.getLegacyBasePotionData().upgraded() ? 2 : 1); } if (attribute.startsWith("is_ambient", 2)) { attribute.fulfill(1); @@ -399,27 +438,31 @@ public static void register() { attribute.fulfill(1); return new ElementTag(0); } - if (!(object.getItemMeta() instanceof PotionMeta potionMeta)) { + if (!(object.getItemMeta() instanceof PotionMeta)) { return null; } - PotionData data = potionMeta.getBasePotionData(); - return new ElementTag(data.getType().name() + "," + (data.isUpgraded() ? 2 : 1) - + "," + data.isExtended() + "," + (object.getMaterial() == Material.SPLASH_POTION)); + LegacyPotionData data = object.getLegacyBasePotionData(); + return new ElementTag(data.type() + "," + (data.upgraded() ? 2 : 1) + + "," + data.extended() + "," + (object.getMaterial() == Material.SPLASH_POTION)); }); } - private static void applyLegacyMapBasePotionData(MapTag input, PotionMeta potionMeta, Mechanism mechanism) { + private static boolean applyLegacyMapBasePotionData(MapTag input, PotionMeta potionMeta, Mechanism mechanism) { if (!input.containsKey("type")) { mechanism.echoError("Must specify a base potion type."); - return; + return true; } ElementTag typeElement = input.getElement("type"); - if (!typeElement.matchesEnum(PotionType.class)) { + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && typeElement.asLowerString().equals("uncraftable")) { + potionMeta.setBasePotionType(null); + return false; + } + PotionType type = Utilities.elementToEnumlike(typeElement, PotionType.class); + if (type == null) { mechanism.echoError("Invalid base potion type '" + typeElement + "': type is required"); - return; + return true; } - PotionType type = PotionType.valueOf(typeElement.asString().toUpperCase()); boolean upgraded = false; boolean extended = false; if (input.containsKey("upgraded")) { @@ -451,17 +494,22 @@ private static void applyLegacyMapBasePotionData(MapTag input, PotionMeta potion } } applyLegacyBasePotionData(potionMeta, type, upgraded, extended, color, mechanism); + return false; } - private static void applyLegacyStringBasePotionData(String input, PotionMeta potionMeta, Mechanism mechanism) { + private static boolean applyLegacyStringBasePotionData(String input, PotionMeta potionMeta, Mechanism mechanism) { String[] d1 = input.split(","); + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && CoreUtilities.equalsIgnoreCase(d1[0], "uncraftable")) { + potionMeta.setBasePotionType(null); + return false; + } PotionType type; try { type = PotionType.valueOf(d1[0].toUpperCase()); } catch (IllegalArgumentException ex) { mechanism.echoError("Invalid base potion type '" + d1[0] + "': type is required"); - return; + return true; } boolean upgraded = CoreUtilities.equalsIgnoreCase(d1[1], "true"); boolean extended = CoreUtilities.equalsIgnoreCase(d1[2], "true"); @@ -476,6 +524,7 @@ private static void applyLegacyStringBasePotionData(String input, PotionMeta pot } } applyLegacyBasePotionData(potionMeta, type, upgraded, extended, color, mechanism); + return false; } private static void applyLegacyBasePotionData(PotionMeta potionMeta, PotionType type, boolean upgraded, boolean extended, ColorTag color, Mechanism mechanism) { @@ -541,4 +590,19 @@ public static PotionEffect parseLegacyEffectString(String str, TagContext contex } return new PotionEffect(type, duration, amplifier, ambient, particles, icon); } + + @Deprecated(forRemoval = true) + public record LegacyPotionData(String type, boolean extended, boolean upgraded) { + public static final LegacyPotionData DEFAULT_DATA = new LegacyPotionData("UNCRAFTABLE", false, false); + + public LegacyPotionData(PotionData data) { + this(data.getType().name(), data.isExtended(), data.isUpgraded()); + } + } + + @Deprecated(forRemoval = true) + public LegacyPotionData getLegacyBasePotionData() { + PotionData data = as(PotionMeta.class).getBasePotionData(); + return data != null ? new LegacyPotionData(data) : LegacyPotionData.DEFAULT_DATA; + } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java index 1efb8d826d..461972636c 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java @@ -344,6 +344,9 @@ public class BukkitImplDeprecations { // Bad candidate for bumping, targets extremely commonly used naming, some of which may be hard to remove (eg stored in flag data). public static Warning oldSpigotNames = new FutureWarning("oldSpigotNames", "Several features (particles, entities, etc.) had alternative naming added by Spigot, which are now deprecated in favor of the official Minecraft naming; see relevant feature's meta docs for more information."); + // Added 2024/11/19 + public static Warning oldPotionEffectType = new FutureWarning("oldPotionEffectType", "Potion effects now use an 'effect' key for the potion effect's type, see meta docs for more information."); + // Added 2024/12/27 public static Warning entityIsSheared = new FutureWarning("entityIsSheared", "'EntityTag.is_sheared' and 'EntityTag.has_pumpkin_head' properties are deprecated in favor of 'EntityTag.sheared'."); diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index b12ce29902..3eb86b9e5c 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -20,6 +20,7 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.*; +import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.scoreboard.Team; import org.bukkit.util.Consumer; @@ -217,4 +218,9 @@ public String getClientBrand(Player player) { public boolean canUseEquipmentSlot(LivingEntity entity, EquipmentSlot slot) { return true; } + + // TODO workaround Paper issue - https://github.com/PaperMC/Paper/issues/11732 + public boolean hasCustomName(PotionMeta meta) { + return meta.hasCustomName(); + } }