diff options
Diffstat (limited to 'patches/api/0473-Proxy-ItemStack-to-CraftItemStack.patch')
-rw-r--r-- | patches/api/0473-Proxy-ItemStack-to-CraftItemStack.patch | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/patches/api/0473-Proxy-ItemStack-to-CraftItemStack.patch b/patches/api/0473-Proxy-ItemStack-to-CraftItemStack.patch new file mode 100644 index 0000000000..246fa425d8 --- /dev/null +++ b/patches/api/0473-Proxy-ItemStack-to-CraftItemStack.patch @@ -0,0 +1,474 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic <[email protected]> +Date: Tue, 14 May 2024 11:57:51 -0700 +Subject: [PATCH] Proxy ItemStack to CraftItemStack + + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 9bdba60fa96edbc4be5dcf54a815579db887048b..330e3013eda204aa9b33d5e1c3104e0b595abdbc 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -285,4 +285,6 @@ public interface UnsafeValues { + @NotNull java.util.List<net.kyori.adventure.text.Component> computeTooltipLines(@NotNull ItemStack itemStack, @NotNull io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, @Nullable org.bukkit.entity.Player player); // Paper - expose itemstack tooltip lines + + <A extends Keyed, M> io.papermc.paper.registry.tag.@Nullable Tag<A> getTag(io.papermc.paper.registry.tag.@NotNull TagKey<A> tagKey); // Paper - hack to get tags for non-server backed registries ++ ++ ItemStack createEmptyStack(); // Paper - proxy ItemStack + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 77edc2e1c5c865db7e101aaa186657ac85edfed9..6fc8bddfcabca8c363e0d9f958f0ce7bc39099f1 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -28,10 +28,38 @@ import org.jetbrains.annotations.Nullable; + * returns false.</b> + */ + public class ItemStack implements Cloneable, ConfigurationSerializable, Translatable, net.kyori.adventure.text.event.HoverEventSource<net.kyori.adventure.text.event.HoverEvent.ShowItem>, net.kyori.adventure.translation.Translatable { // Paper +- private Material type = Material.AIR; +- private int amount = 0; ++ private ItemStack craftDelegate; // Paper - always delegate to server-backed stack + private MaterialData data = null; +- private ItemMeta meta; ++ ++ // Paper start - add static factory methods ++ /** ++ * Creates an itemstack with the specified item type and a count of 1. ++ * ++ * @param type the item type to use ++ * @return a new itemstack ++ * @throws IllegalArgumentException if the Material provided is not an item ({@link Material#isItem()}) ++ */ ++ @org.jetbrains.annotations.Contract(value = "_ -> new", pure = true) ++ public static @NotNull ItemStack of(final @NotNull Material type) { ++ return of(type, 1); ++ } ++ ++ /** ++ * Creates an itemstack with the specified item type and count. ++ * ++ * @param type the item type to use ++ * @param amount the count of items in the stack ++ * @return a new itemstack ++ * @throws IllegalArgumentException if the Material provided is not an item ({@link Material#isItem()}) ++ * @throws IllegalArgumentException if the amount is less than 1 ++ */ ++ @org.jetbrains.annotations.Contract(value = "_, _ -> new", pure = true) ++ public static @NotNull ItemStack of(final @NotNull Material type, final int amount) { ++ Preconditions.checkArgument(type.asItemType() != null, type + " isn't an item"); ++ Preconditions.checkArgument(amount > 0, "amount must be greater than 0"); ++ return java.util.Objects.requireNonNull(type.asItemType(), type + " is not an item").createItemStack(amount); // Paper - delegate ++ } ++ // Paper end + + @Utility + protected ItemStack() {} +@@ -44,7 +72,10 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * {@link Material#isItem()} returns false.</b> + * + * @param type item material ++ * @apiNote use {@link #of(Material)} ++ * @see #of(Material) + */ ++ @org.jetbrains.annotations.ApiStatus.Obsolete(since = "1.21") // Paper + public ItemStack(@NotNull final Material type) { + this(type, 1); + } +@@ -58,7 +89,10 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * + * @param type item material + * @param amount stack size ++ * @apiNote Use {@link #of(Material, int)} ++ * @see #of(Material, int) + */ ++ @org.jetbrains.annotations.ApiStatus.Obsolete(since = "1.21") // Paper + public ItemStack(@NotNull final Material type, final int amount) { + this(type, amount, (short) 0); + } +@@ -93,8 +127,9 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + type = Bukkit.getUnsafe().fromLegacy(new MaterialData(type, data == null ? (byte) damage : data), true); + } + } +- this.type = type; +- this.amount = amount; ++ // Paper start - create delegate ++ this.craftDelegate = type == Material.AIR ? ItemStack.empty() : ItemStack.of(type, amount); ++ // Paper end - create delegate + if (damage != 0) { + setDurability(damage); + } +@@ -109,17 +144,16 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * @param stack the stack to copy + * @throws IllegalArgumentException if the specified stack is null or + * returns an item meta not created by the item factory ++ * @apiNote Use {@link #clone()} ++ * @see #clone() + */ ++ @org.jetbrains.annotations.ApiStatus.Obsolete(since = "1.21") // Paper + public ItemStack(@NotNull final ItemStack stack) throws IllegalArgumentException { + Preconditions.checkArgument(stack != null, "Cannot copy null stack"); +- this.type = stack.getType(); +- this.amount = stack.getAmount(); +- if (this.type.isLegacy()) { ++ this.craftDelegate = stack.clone(); // Paper - delegate ++ if (stack.getType().isLegacy()) { + this.data = stack.getData(); + } +- if (stack.hasItemMeta()) { +- setItemMeta0(stack.getItemMeta(), type); +- } + } + + /** +@@ -127,10 +161,9 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * + * @return Type of the items in this stack + */ +- @Utility + @NotNull + public Material getType() { +- return type; ++ return this.craftDelegate.getType(); // Paper - delegate + } + + /** +@@ -153,19 +186,10 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * Using this method in ItemStacks passed in events will result in undefined behavior. + * @see ItemStack#withType(Material) + */ +- @Utility + @Deprecated // Paper + public void setType(@NotNull Material type) { + Preconditions.checkArgument(type != null, "Material cannot be null"); +- this.type = type; +- if (this.meta != null) { +- this.meta = Bukkit.getItemFactory().asMetaFor(meta, type); +- } +- if (type.isLegacy()) { +- createData((byte) 0); +- } else { +- this.data = null; +- } ++ this.craftDelegate.setType(type); // Paper - delegate + } + // Paper start + /** +@@ -177,12 +201,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + @NotNull + @org.jetbrains.annotations.Contract(value = "_ -> new", pure = true) + public ItemStack withType(@NotNull Material type) { +- ItemStack itemStack = new ItemStack(type, this.amount); +- if (this.hasItemMeta()) { +- itemStack.setItemMeta(this.getItemMeta()); +- } +- +- return itemStack; ++ return this.craftDelegate.withType(type); // Paper - delegate + } + // Paper end + +@@ -192,7 +211,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * @return Amount of items in this stack + */ + public int getAmount() { +- return amount; ++ return this.craftDelegate.getAmount(); // Paper - delegate + } + + /** +@@ -201,7 +220,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * @param amount New amount of items in this stack + */ + public void setAmount(int amount) { +- this.amount = amount; ++ this.craftDelegate.setAmount(amount); // Paper - delegate + } + + /** +@@ -254,11 +273,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + */ + @Deprecated + public void setDurability(final short durability) { +- ItemMeta meta = getItemMeta(); +- if (meta != null) { +- ((Damageable) meta).setDamage(durability); +- setItemMeta(meta); +- } ++ this.craftDelegate.setDurability(durability); // Paper - delegate + } + + /** +@@ -269,8 +284,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + */ + @Deprecated + public short getDurability() { +- ItemMeta meta = getItemMeta(); +- return (meta == null) ? 0 : (short) ((Damageable) meta).getDamage(); ++ return this.craftDelegate.getDurability(); // Paper - delegate + } + + /** +@@ -282,17 +296,12 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * + * @return The maximum you can stack this item to. + */ +- @Utility + public int getMaxStackSize() { +- if (meta != null && meta.hasMaxStackSize()) { +- return meta.getMaxStackSize(); +- } +- +- return getType().getMaxStackSize(); ++ return this.craftDelegate.getMaxStackSize(); // Paper - delegate + } + + private void createData(final byte data) { +- this.data = type.getNewData(data); ++ this.data = this.craftDelegate.getType().getNewData(data); // Paper + } + + @Override +@@ -306,17 +315,8 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + } + + @Override +- @Utility + public boolean equals(Object obj) { +- if (this == obj) { +- return true; +- } +- if (!(obj instanceof ItemStack)) { +- return false; +- } +- +- ItemStack stack = (ItemStack) obj; +- return getAmount() == stack.getAmount() && isSimilar(stack); ++ return this.craftDelegate.equals(obj); // Paper - delegate + } + + /** +@@ -326,49 +326,19 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * @param stack the item stack to compare to + * @return true if the two stacks are equal, ignoring the amount + */ +- @Utility + public boolean isSimilar(@Nullable ItemStack stack) { +- if (stack == null) { +- return false; +- } +- if (stack == this) { +- return true; +- } +- Material comparisonType = (this.type.isLegacy()) ? Bukkit.getUnsafe().fromLegacy(this.getData(), true) : this.type; // This may be called from legacy item stacks, try to get the right material +- return comparisonType == stack.getType() && /* getDurability() == stack.getDurability() && */hasItemMeta() == stack.hasItemMeta() && (hasItemMeta() ? Bukkit.getItemFactory().equals(getItemMeta(), stack.getItemMeta()) : true); // Paper - remove redundant item durability check ++ return this.craftDelegate.isSimilar(stack); // Paper - delegate + } + + @NotNull + @Override + public ItemStack clone() { +- try { +- ItemStack itemStack = (ItemStack) super.clone(); +- +- if (this.meta != null) { +- itemStack.meta = this.meta.clone(); +- } +- +- if (this.data != null) { +- itemStack.data = this.data.clone(); +- } +- +- return itemStack; +- } catch (CloneNotSupportedException e) { +- throw new Error(e); +- } ++ return this.craftDelegate.clone(); // Paper - delegate + } + + @Override +- @Utility + public int hashCode() { +- int hash = 1; +- +- hash = hash * 31 + getType().hashCode(); +- hash = hash * 31 + getAmount(); +- hash = hash * 31 + (getDurability() & 0xffff); +- hash = hash * 31 + (hasItemMeta() ? (meta == null ? getItemMeta().hashCode() : meta.hashCode()) : 0); +- +- return hash; ++ return this.craftDelegate.hashCode(); // Paper - delegate + } + + /** +@@ -378,7 +348,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * @return True if this has the given enchantment + */ + public boolean containsEnchantment(@NotNull Enchantment ench) { +- return meta == null ? false : meta.hasEnchant(ench); ++ return this.craftDelegate.containsEnchantment(ench); // Paper - delegate + } + + /** +@@ -388,7 +358,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * @return Level of the enchantment, or 0 + */ + public int getEnchantmentLevel(@NotNull Enchantment ench) { +- return meta == null ? 0 : meta.getEnchantLevel(ench); ++ return this.craftDelegate.getEnchantmentLevel(ench); // Paper - delegate + } + + /** +@@ -398,7 +368,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + */ + @NotNull + public Map<Enchantment, Integer> getEnchantments() { +- return meta == null ? ImmutableMap.<Enchantment, Integer>of() : meta.getEnchants(); ++ return this.craftDelegate.getEnchantments(); // Paper - delegate + } + + /** +@@ -474,10 +444,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * @param level Level of the enchantment + */ + public void addUnsafeEnchantment(@NotNull Enchantment ench, int level) { +- ItemMeta itemMeta = (meta == null ? meta = Bukkit.getItemFactory().getItemMeta(type) : meta); +- if (itemMeta != null) { +- itemMeta.addEnchant(ench, level, true); +- } ++ this.craftDelegate.addUnsafeEnchantment(ench, level); // Paper - delegate + } + + /** +@@ -488,23 +455,14 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * @return Previous level, or 0 + */ + public int removeEnchantment(@NotNull Enchantment ench) { +- int level = getEnchantmentLevel(ench); +- if (level == 0 || meta == null) { +- return level; +- } +- meta.removeEnchant(ench); +- return level; ++ return this.craftDelegate.removeEnchantment(ench); // Paper - delegate + } + + /** + * Removes all enchantments on this ItemStack. + */ + public void removeEnchantments() { +- if (meta == null) { +- return; +- } +- +- meta.removeEnchantments(); ++ this.craftDelegate.removeEnchantments(); // Paper - delegate + } + + @Override +@@ -660,7 +618,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + */ + @UndefinedNullability // Paper + public ItemMeta getItemMeta() { +- return this.meta == null ? Bukkit.getItemFactory().getItemMeta(this.type) : this.meta.clone(); ++ return this.craftDelegate.getItemMeta(); // Paper - delegate + } + + /** +@@ -669,7 +627,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * @return Returns true if some meta data has been set for this item + */ + public boolean hasItemMeta() { +- return !Bukkit.getItemFactory().equals(meta, null); ++ return this.craftDelegate.hasItemMeta(); // Paper - delegate + } + + /** +@@ -682,28 +640,10 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * the {@link ItemFactory} + */ + public boolean setItemMeta(@Nullable ItemMeta itemMeta) { +- return setItemMeta0(itemMeta, type); ++ return this.craftDelegate.setItemMeta(itemMeta); // Paper - delegate + } + +- /* +- * Cannot be overridden, so it's safe for constructor call +- */ +- private boolean setItemMeta0(@Nullable ItemMeta itemMeta, @NotNull Material material) { +- if (itemMeta == null) { +- this.meta = null; +- return true; +- } +- if (!Bukkit.getItemFactory().isApplicable(itemMeta, material)) { +- return false; +- } +- this.meta = Bukkit.getItemFactory().asMetaFor(itemMeta, material); +- +- if (this.meta == itemMeta) { +- this.meta = itemMeta.clone(); +- } +- +- return true; +- } ++ // Paper - delegate + + @Override + @NotNull +@@ -894,11 +834,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + } + + public int getMaxItemUseDuration(@NotNull final org.bukkit.entity.LivingEntity entity) { +- if (type == null || type == Material.AIR || !type.isItem()) { +- return 0; +- } +- // Requires access to NMS +- return ensureServerConversions().getMaxItemUseDuration(entity); ++ return this.craftDelegate.getMaxItemUseDuration(entity); // Paper - delegate + } + + /** +@@ -1148,7 +1084,8 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + */ + @NotNull + public static ItemStack empty() { +- return new ItemStack(); ++ //noinspection deprecation ++ return Bukkit.getUnsafe().createEmptyStack(); // Paper - proxy ItemStack + } + + /** +@@ -1156,7 +1093,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * it is either air or the stack has a size of 0. + */ + public boolean isEmpty() { +- return type.isAir() || amount <= 0; ++ return this.craftDelegate.isEmpty(); // Paper - delegate + } + // Paper end + // Paper start - expose itemstack tooltip lines +diff --git a/src/test/java/org/bukkit/configuration/ConfigurationSectionTest.java b/src/test/java/org/bukkit/configuration/ConfigurationSectionTest.java +index ee5bc86f47cf5599e4c5c34e3a9084f86d74bdb7..c6b49c7e0a3357566fc859d4f0c76e77fefbd371 100644 +--- a/src/test/java/org/bukkit/configuration/ConfigurationSectionTest.java ++++ b/src/test/java/org/bukkit/configuration/ConfigurationSectionTest.java +@@ -547,6 +547,7 @@ public abstract class ConfigurationSectionTest { + } + + @Test ++ @org.junit.jupiter.api.Disabled("ItemStack can't exist without the Server, test moved to server") + public void testGetItemStack_String() { + ConfigurationSection section = getConfigurationSection(); + String key = "exists"; +@@ -559,6 +560,7 @@ public abstract class ConfigurationSectionTest { + } + + @Test ++ @org.junit.jupiter.api.Disabled("ItemStack can't exist without the Server, test moved to server") + public void testGetItemStack_String_ItemStack() { + ConfigurationSection section = getConfigurationSection(); + String key = "exists"; +@@ -572,6 +574,7 @@ public abstract class ConfigurationSectionTest { + } + + @Test ++ @org.junit.jupiter.api.Disabled("ItemStack can't exist without the Server, test moved to server") + public void testIsItemStack() { + ConfigurationSection section = getConfigurationSection(); + String key = "exists"; |