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();
+ }
}