Mirror von
https://github.com/PaperMC/Paper.git
synchronisiert 2024-12-15 02:50:09 +01:00
Delegate ItemStack (#10852)
Dieser Commit ist enthalten in:
Ursprung
13992b17c7
Commit
bf8552f0f0
@ -19,3 +19,55 @@ index 637fa73d4366c2d88e2716e5c8d3465706d788a7..0f03c546ecdd6383fb36a362d18d6fb5
|
||||
this.flicker = flicker;
|
||||
this.trail = trail;
|
||||
this.colors = colors;
|
||||
diff --git a/src/main/java/org/bukkit/inventory/meta/Damageable.java b/src/main/java/org/bukkit/inventory/meta/Damageable.java
|
||||
index ff6818b6d9e0207eafdd749928f33aeac3f27191..992f39da07bafe9769effaa7dc6adc018c89329d 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/meta/Damageable.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/meta/Damageable.java
|
||||
@@ -9,14 +9,17 @@ import org.jetbrains.annotations.Nullable;
|
||||
public interface Damageable extends ItemMeta {
|
||||
|
||||
/**
|
||||
- * Checks to see if this item has damage
|
||||
+ * Checks to see if this item has damage greater than 0.
|
||||
*
|
||||
- * @return true if this has damage
|
||||
+ * @return true if this has damage > 0
|
||||
*/
|
||||
boolean hasDamage();
|
||||
|
||||
/**
|
||||
* Gets the damage
|
||||
+ * <p>
|
||||
+ * Call {@link #hasDamageValue()} to be sure
|
||||
+ * a damage value is set.
|
||||
*
|
||||
* @return the damage
|
||||
*/
|
||||
@@ -26,9 +29,27 @@ public interface Damageable extends ItemMeta {
|
||||
* Sets the damage
|
||||
*
|
||||
* @param damage item damage
|
||||
+ * @see #resetDamage() to reset and clear the damage data component
|
||||
*/
|
||||
void setDamage(int damage);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Checks if any damage value, including 0,
|
||||
+ * is set on this meta.
|
||||
+ *
|
||||
+ * @return true if any value is set
|
||||
+ */
|
||||
+ boolean hasDamageValue();
|
||||
+
|
||||
+ /**
|
||||
+ * Clears the damage component from the meta. Differs
|
||||
+ * from {@code setDamage(0)} in that it removes the component
|
||||
+ * instead of adding the component with a value of 0.
|
||||
+ */
|
||||
+ void resetDamage();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Checks to see if this item has a maximum amount of damage.
|
||||
*
|
||||
|
472
patches/api/0478-Proxy-ItemStack-to-CraftItemStack.patch
Normale Datei
472
patches/api/0478-Proxy-ItemStack-to-CraftItemStack.patch
Normale Datei
@ -0,0 +1,472 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
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 7332034bb1753f48f7904dafab1ef4b3ee117ea3..11bccf6c27b8b2a2ed558a1375a3b3adc7952076 100644
|
||||
--- a/src/main/java/org/bukkit/UnsafeValues.java
|
||||
+++ b/src/main/java/org/bukkit/UnsafeValues.java
|
||||
@@ -277,4 +277,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 7f5633e7689b82b937d5b985c3e6ae15dc94a20f..da91938ff941bb5903dcbd430c68c5980c01b57b 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,7 @@ 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;
|
||||
+ this.craftDelegate = ItemStack.of(type, amount); // Paper - create delegate
|
||||
if (damage != 0) {
|
||||
setDurability(damage);
|
||||
}
|
||||
@@ -109,17 +142,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 +159,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 +184,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 +199,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 +209,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 +218,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 +271,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 +282,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 +294,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 +313,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 +324,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 +346,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 +356,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 +366,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 +442,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 +453,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 +616,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 +625,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 +638,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
|
||||
@@ -807,11 +745,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
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1061,7 +995,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
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1069,7 +1004,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";
|
@ -0,0 +1,434 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 12 Jun 2024 10:29:30 -0700
|
||||
Subject: [PATCH] Make a PDC view accessible directly from ItemStack
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/persistence/PersistentDataContainerView.java b/src/main/java/io/papermc/paper/persistence/PersistentDataContainerView.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4a4949fde3f03e2ea9d2dde245f7dea119e202bf
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/persistence/PersistentDataContainerView.java
|
||||
@@ -0,0 +1,167 @@
|
||||
+package io.papermc.paper.persistence;
|
||||
+
|
||||
+import java.util.Set;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
+import org.bukkit.persistence.PersistentDataContainer;
|
||||
+import org.bukkit.persistence.PersistentDataHolder;
|
||||
+import org.bukkit.persistence.PersistentDataType;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+
|
||||
+/**
|
||||
+ * This represents a view of a persistent data container. No
|
||||
+ * methods on this interface mutate the container.
|
||||
+ * @see PersistentDataContainer
|
||||
+ */
|
||||
+@ApiStatus.NonExtendable
|
||||
+public interface PersistentDataContainerView {
|
||||
+
|
||||
+ /**
|
||||
+ * Returns if the persistent metadata provider has metadata registered
|
||||
+ * matching the provided parameters.
|
||||
+ * <p>
|
||||
+ * This method will only return true if the found value has the same primitive
|
||||
+ * data type as the provided key.
|
||||
+ * <p>
|
||||
+ * Storing a value using a custom {@link PersistentDataType} implementation
|
||||
+ * will not store the complex data type. Therefore storing a UUID (by
|
||||
+ * storing a byte[]) will match has("key" ,
|
||||
+ * {@link PersistentDataType#BYTE_ARRAY}). Likewise a stored byte[] will
|
||||
+ * always match your UUID {@link PersistentDataType} even if it is not 16
|
||||
+ * bytes long.
|
||||
+ * <p>
|
||||
+ * This method is only usable for custom object keys. Overwriting existing
|
||||
+ * tags, like the display name, will not work as the values are stored
|
||||
+ * using your namespace.
|
||||
+ *
|
||||
+ * @param key the key the value is stored under
|
||||
+ * @param type the type the primative stored value has to match
|
||||
+ * @param <P> the generic type of the stored primitive
|
||||
+ * @param <C> the generic type of the eventually created complex object
|
||||
+ *
|
||||
+ * @return if a value with the provided key and type exists
|
||||
+ *
|
||||
+ * @throws IllegalArgumentException if the key to look up is null
|
||||
+ * @throws IllegalArgumentException if the type to cast the found object to is
|
||||
+ * null
|
||||
+ */
|
||||
+ <P, C> boolean has(@NonNull NamespacedKey key, @NonNull PersistentDataType<P, C> type);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns if the persistent metadata provider has metadata registered matching
|
||||
+ * the provided parameters.
|
||||
+ * <p>
|
||||
+ * This method will return true as long as a value with the given key exists,
|
||||
+ * regardless of its type.
|
||||
+ * <p>
|
||||
+ * This method is only usable for custom object keys. Overwriting existing tags,
|
||||
+ * like the display name, will not work as the values are stored using your
|
||||
+ * namespace.
|
||||
+ *
|
||||
+ * @param key the key the value is stored under
|
||||
+ *
|
||||
+ * @return if a value with the provided key exists
|
||||
+ *
|
||||
+ * @throws IllegalArgumentException if the key to look up is null
|
||||
+ */
|
||||
+ boolean has(@NonNull NamespacedKey key);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the metadata value that is stored on the
|
||||
+ * {@link PersistentDataHolder} instance.
|
||||
+ *
|
||||
+ * @param key the key to look up in the custom tag map
|
||||
+ * @param type the type the value must have and will be casted to
|
||||
+ * @param <P> the generic type of the stored primitive
|
||||
+ * @param <C> the generic type of the eventually created complex object
|
||||
+ *
|
||||
+ * @return the value or {@code null} if no value was mapped under the given
|
||||
+ * value
|
||||
+ *
|
||||
+ * @throws IllegalArgumentException if the key to look up is null
|
||||
+ * @throws IllegalArgumentException if the type to cast the found object to is
|
||||
+ * null
|
||||
+ * @throws IllegalArgumentException if a value exists under the given key,
|
||||
+ * but cannot be accessed using the given type
|
||||
+ * @throws IllegalArgumentException if no suitable adapter was found for
|
||||
+ * the {@link
|
||||
+ * PersistentDataType#getPrimitiveType()}
|
||||
+ */
|
||||
+ <P, C> @Nullable C get(@NonNull NamespacedKey key, @NonNull PersistentDataType<P, C> type);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the metadata value that is stored on the
|
||||
+ * {@link PersistentDataHolder} instance. If the value does not exist in the
|
||||
+ * container, the default value provided is returned.
|
||||
+ *
|
||||
+ * @param key the key to look up in the custom tag map
|
||||
+ * @param type the type the value must have and will be casted to
|
||||
+ * @param defaultValue the default value to return if no value was found for
|
||||
+ * the provided key
|
||||
+ * @param <P> the generic type of the stored primitive
|
||||
+ * @param <C> the generic type of the eventually created complex object
|
||||
+ *
|
||||
+ * @return the value or the default value if no value was mapped under the
|
||||
+ * given key
|
||||
+ *
|
||||
+ * @throws IllegalArgumentException if the key to look up is null
|
||||
+ * @throws IllegalArgumentException if the type to cast the found object to is
|
||||
+ * null
|
||||
+ * @throws IllegalArgumentException if a value exists under the given key,
|
||||
+ * but cannot be accessed using the given type
|
||||
+ * @throws IllegalArgumentException if no suitable adapter was found for
|
||||
+ * the {@link PersistentDataType#getPrimitiveType()}
|
||||
+ */
|
||||
+ <P, C> @NonNull C getOrDefault(@NonNull NamespacedKey key, @NonNull PersistentDataType<P, C> type, @NonNull C defaultValue);
|
||||
+
|
||||
+ /**
|
||||
+ * Get the set of keys present on this {@link PersistentDataContainer}
|
||||
+ * instance.
|
||||
+ *
|
||||
+ * Any changes made to the returned set will not be reflected on the
|
||||
+ * instance.
|
||||
+ *
|
||||
+ * @return the key set
|
||||
+ */
|
||||
+ @NonNull Set<NamespacedKey> getKeys();
|
||||
+
|
||||
+ /**
|
||||
+ * Returns if the container instance is empty, therefore has no entries
|
||||
+ * inside it.
|
||||
+ *
|
||||
+ * @return the boolean
|
||||
+ */
|
||||
+ boolean isEmpty();
|
||||
+
|
||||
+ /**
|
||||
+ * Copies all values from this {@link PersistentDataContainer} to the provided
|
||||
+ * container.
|
||||
+ * <p>
|
||||
+ * This method only copies custom object keys. Existing tags, like the display
|
||||
+ * name, will not be copied as the values are stored using your namespace.
|
||||
+ *
|
||||
+ * @param other the container to copy to
|
||||
+ * @param replace whether to replace any matching values in the target container
|
||||
+ *
|
||||
+ * @throws IllegalArgumentException if the other container is null
|
||||
+ */
|
||||
+ void copyTo(@NonNull PersistentDataContainer other, boolean replace);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the adapter context this tag container uses.
|
||||
+ *
|
||||
+ * @return the tag context
|
||||
+ */
|
||||
+ @NonNull PersistentDataAdapterContext getAdapterContext();
|
||||
+
|
||||
+ /**
|
||||
+ * Serialize this {@link PersistentDataContainer} instance to a
|
||||
+ * byte array.
|
||||
+ *
|
||||
+ * @return a binary representation of this container
|
||||
+ * @throws java.io.IOException if we fail to write this container to a byte array
|
||||
+ */
|
||||
+ byte @NonNull [] serializeToBytes() throws java.io.IOException;
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/persistence/PersistentDataViewHolder.java b/src/main/java/io/papermc/paper/persistence/PersistentDataViewHolder.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9789916f949374bfb50da535b076180700f7ae73
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/persistence/PersistentDataViewHolder.java
|
||||
@@ -0,0 +1,23 @@
|
||||
+package io.papermc.paper.persistence;
|
||||
+
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+
|
||||
+/**
|
||||
+ * The {@link PersistentDataViewHolder} interface defines an object that can view
|
||||
+ * custom persistent data on it.
|
||||
+ */
|
||||
+@ApiStatus.NonExtendable
|
||||
+public interface PersistentDataViewHolder {
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a custom tag container view capable of viewing tags on the object.
|
||||
+ * <p>
|
||||
+ * Note that the tags stored on this container are all stored under their
|
||||
+ * own custom namespace therefore modifying default tags using this
|
||||
+ * {@link PersistentDataViewHolder} is impossible.
|
||||
+ *
|
||||
+ * @return the persistent data container view
|
||||
+ */
|
||||
+ @NonNull PersistentDataContainerView getPersistentDataContainer();
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index da91938ff941bb5903dcbd430c68c5980c01b57b..f603b5b6ba80af919f415322583a8345a5b1358a 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -27,7 +27,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* use this class to encapsulate Materials for which {@link Material#isItem()}
|
||||
* 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
|
||||
+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, io.papermc.paper.persistence.PersistentDataViewHolder { // Paper
|
||||
private ItemStack craftDelegate; // Paper - always delegate to server-backed stack
|
||||
private MaterialData data = null;
|
||||
|
||||
@@ -61,6 +61,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Paper start - pdc
|
||||
+ @Override
|
||||
+ public io.papermc.paper.persistence.@NotNull PersistentDataContainerView getPersistentDataContainer() {
|
||||
+ return this.craftDelegate.getPersistentDataContainer();
|
||||
+ }
|
||||
+ // Paper end - pdc
|
||||
+
|
||||
@Utility
|
||||
protected ItemStack() {}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/persistence/PersistentDataContainer.java b/src/main/java/org/bukkit/persistence/PersistentDataContainer.java
|
||||
index decf3b1949d4653a9fb01684b93ff91048137076..0f40eb52f6e2a5b6932cf9f223c1bbe9ab9eab1b 100644
|
||||
--- a/src/main/java/org/bukkit/persistence/PersistentDataContainer.java
|
||||
+++ b/src/main/java/org/bukkit/persistence/PersistentDataContainer.java
|
||||
@@ -9,7 +9,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* This interface represents a map like object, capable of storing custom tags
|
||||
* in it.
|
||||
*/
|
||||
-public interface PersistentDataContainer {
|
||||
+public interface PersistentDataContainer extends io.papermc.paper.persistence.PersistentDataContainerView { // Paper - split up view and mutable
|
||||
|
||||
/**
|
||||
* Stores a metadata value on the {@link PersistentDataHolder} instance.
|
||||
@@ -33,118 +33,7 @@ public interface PersistentDataContainer {
|
||||
* the {@link PersistentDataType#getPrimitiveType()}
|
||||
*/
|
||||
<P, C> void set(@NotNull NamespacedKey key, @NotNull PersistentDataType<P, C> type, @NotNull C value);
|
||||
-
|
||||
- /**
|
||||
- * Returns if the persistent metadata provider has metadata registered
|
||||
- * matching the provided parameters.
|
||||
- * <p>
|
||||
- * This method will only return true if the found value has the same primitive
|
||||
- * data type as the provided key.
|
||||
- * <p>
|
||||
- * Storing a value using a custom {@link PersistentDataType} implementation
|
||||
- * will not store the complex data type. Therefore storing a UUID (by
|
||||
- * storing a byte[]) will match has("key" ,
|
||||
- * {@link PersistentDataType#BYTE_ARRAY}). Likewise a stored byte[] will
|
||||
- * always match your UUID {@link PersistentDataType} even if it is not 16
|
||||
- * bytes long.
|
||||
- * <p>
|
||||
- * This method is only usable for custom object keys. Overwriting existing
|
||||
- * tags, like the display name, will not work as the values are stored
|
||||
- * using your namespace.
|
||||
- *
|
||||
- * @param key the key the value is stored under
|
||||
- * @param type the type the primative stored value has to match
|
||||
- * @param <P> the generic type of the stored primitive
|
||||
- * @param <C> the generic type of the eventually created complex object
|
||||
- *
|
||||
- * @return if a value with the provided key and type exists
|
||||
- *
|
||||
- * @throws IllegalArgumentException if the key to look up is null
|
||||
- * @throws IllegalArgumentException if the type to cast the found object to is
|
||||
- * null
|
||||
- */
|
||||
- <P, C> boolean has(@NotNull NamespacedKey key, @NotNull PersistentDataType<P, C> type);
|
||||
-
|
||||
- /**
|
||||
- * Returns if the persistent metadata provider has metadata registered matching
|
||||
- * the provided parameters.
|
||||
- * <p>
|
||||
- * This method will return true as long as a value with the given key exists,
|
||||
- * regardless of its type.
|
||||
- * <p>
|
||||
- * This method is only usable for custom object keys. Overwriting existing tags,
|
||||
- * like the display name, will not work as the values are stored using your
|
||||
- * namespace.
|
||||
- *
|
||||
- * @param key the key the value is stored under
|
||||
- *
|
||||
- * @return if a value with the provided key exists
|
||||
- *
|
||||
- * @throws IllegalArgumentException if the key to look up is null
|
||||
- */
|
||||
- boolean has(@NotNull NamespacedKey key);
|
||||
-
|
||||
- /**
|
||||
- * Returns the metadata value that is stored on the
|
||||
- * {@link PersistentDataHolder} instance.
|
||||
- *
|
||||
- * @param key the key to look up in the custom tag map
|
||||
- * @param type the type the value must have and will be casted to
|
||||
- * @param <P> the generic type of the stored primitive
|
||||
- * @param <C> the generic type of the eventually created complex object
|
||||
- *
|
||||
- * @return the value or {@code null} if no value was mapped under the given
|
||||
- * value
|
||||
- *
|
||||
- * @throws IllegalArgumentException if the key to look up is null
|
||||
- * @throws IllegalArgumentException if the type to cast the found object to is
|
||||
- * null
|
||||
- * @throws IllegalArgumentException if a value exists under the given key,
|
||||
- * but cannot be accessed using the given type
|
||||
- * @throws IllegalArgumentException if no suitable adapter was found for
|
||||
- * the {@link
|
||||
- * PersistentDataType#getPrimitiveType()}
|
||||
- */
|
||||
- @Nullable
|
||||
- <P, C> C get(@NotNull NamespacedKey key, @NotNull PersistentDataType<P, C> type);
|
||||
-
|
||||
- /**
|
||||
- * Returns the metadata value that is stored on the
|
||||
- * {@link PersistentDataHolder} instance. If the value does not exist in the
|
||||
- * container, the default value provided is returned.
|
||||
- *
|
||||
- * @param key the key to look up in the custom tag map
|
||||
- * @param type the type the value must have and will be casted to
|
||||
- * @param defaultValue the default value to return if no value was found for
|
||||
- * the provided key
|
||||
- * @param <P> the generic type of the stored primitive
|
||||
- * @param <C> the generic type of the eventually created complex object
|
||||
- *
|
||||
- * @return the value or the default value if no value was mapped under the
|
||||
- * given key
|
||||
- *
|
||||
- * @throws IllegalArgumentException if the key to look up is null
|
||||
- * @throws IllegalArgumentException if the type to cast the found object to is
|
||||
- * null
|
||||
- * @throws IllegalArgumentException if a value exists under the given key,
|
||||
- * but cannot be accessed using the given type
|
||||
- * @throws IllegalArgumentException if no suitable adapter was found for
|
||||
- * the {@link PersistentDataType#getPrimitiveType()}
|
||||
- */
|
||||
- @NotNull
|
||||
- <P, C> C getOrDefault(@NotNull NamespacedKey key, @NotNull PersistentDataType<P, C> type, @NotNull C defaultValue);
|
||||
-
|
||||
- /**
|
||||
- * Get the set of keys present on this {@link PersistentDataContainer}
|
||||
- * instance.
|
||||
- *
|
||||
- * Any changes made to the returned set will not be reflected on the
|
||||
- * instance.
|
||||
- *
|
||||
- * @return the key set
|
||||
- */
|
||||
- @NotNull
|
||||
- Set<NamespacedKey> getKeys();
|
||||
+ // Paper - move to PersistentDataContainerView
|
||||
|
||||
/**
|
||||
* Removes a custom key from the {@link PersistentDataHolder} instance.
|
||||
@@ -154,47 +43,10 @@ public interface PersistentDataContainer {
|
||||
* @throws IllegalArgumentException if the provided key is null
|
||||
*/
|
||||
void remove(@NotNull NamespacedKey key);
|
||||
-
|
||||
- /**
|
||||
- * Returns if the container instance is empty, therefore has no entries
|
||||
- * inside it.
|
||||
- *
|
||||
- * @return the boolean
|
||||
- */
|
||||
- boolean isEmpty();
|
||||
-
|
||||
- /**
|
||||
- * Copies all values from this {@link PersistentDataContainer} to the provided
|
||||
- * container.
|
||||
- * <p>
|
||||
- * This method only copies custom object keys. Existing tags, like the display
|
||||
- * name, will not be copied as the values are stored using your namespace.
|
||||
- *
|
||||
- * @param other the container to copy to
|
||||
- * @param replace whether to replace any matching values in the target container
|
||||
- *
|
||||
- * @throws IllegalArgumentException if the other container is null
|
||||
- */
|
||||
- void copyTo(@NotNull PersistentDataContainer other, boolean replace);
|
||||
-
|
||||
- /**
|
||||
- * Returns the adapter context this tag container uses.
|
||||
- *
|
||||
- * @return the tag context
|
||||
- */
|
||||
- @NotNull
|
||||
- PersistentDataAdapterContext getAdapterContext();
|
||||
+ // Paper - move to PersistentDataContainerView
|
||||
|
||||
// Paper start - byte array serialization
|
||||
- /**
|
||||
- * Serialize this {@link PersistentDataContainer} instance to a
|
||||
- * byte array.
|
||||
- *
|
||||
- * @return a binary representation of this container
|
||||
- * @throws java.io.IOException if we fail to write this container to a byte array
|
||||
- */
|
||||
- byte @NotNull [] serializeToBytes() throws java.io.IOException;
|
||||
-
|
||||
+ // Paper - move to PersistentDataContainerView
|
||||
/**
|
||||
* Read values from a serialised byte array into this
|
||||
* {@link PersistentDataContainer} instance.
|
||||
diff --git a/src/main/java/org/bukkit/persistence/PersistentDataHolder.java b/src/main/java/org/bukkit/persistence/PersistentDataHolder.java
|
||||
index 80b277cc57f092f04fbf7810ac78d250b207b775..71f33c1265bc753ef40108ffce0d4bd8656d2903 100644
|
||||
--- a/src/main/java/org/bukkit/persistence/PersistentDataHolder.java
|
||||
+++ b/src/main/java/org/bukkit/persistence/PersistentDataHolder.java
|
||||
@@ -5,8 +5,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* The {@link PersistentDataHolder} interface defines an object that can store
|
||||
* custom persistent meta data on it.
|
||||
+ * <p>Prefer using {@link io.papermc.paper.persistence.PersistentDataViewHolder} for read-only operations
|
||||
+ * as it covers more types.</p>
|
||||
*/
|
||||
-public interface PersistentDataHolder {
|
||||
+public interface PersistentDataHolder extends io.papermc.paper.persistence.PersistentDataViewHolder { // Paper
|
||||
|
||||
/**
|
||||
* Returns a custom tag container capable of storing tags on the object.
|
@ -25,10 +25,10 @@ index a71717fe99e78c480747cc61ab30b53b6667fde7..080ab25d3585552c1abd62a9992d48bf
|
||||
@Override
|
||||
diff --git a/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6b8d360ef86e181a680ad77f28b7dd7368dddfe7
|
||||
index 0000000000000000000000000000000000000000..9f8abe2376f16aeffe4e9f90a2da04b7e3a55429
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java
|
||||
@@ -0,0 +1,48 @@
|
||||
@@ -0,0 +1,41 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+import org.bukkit.Material;
|
||||
@ -69,11 +69,4 @@ index 0000000000000000000000000000000000000000..6b8d360ef86e181a680ad77f28b7dd73
|
||||
+
|
||||
+ assertFalse(diamond.canRepair(new ItemStack(Material.OAK_BUTTON)), "diamond can repair oak button");
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testInvalidItem() {
|
||||
+ ItemStack badItemStack = new ItemStack(Material.ACACIA_WALL_SIGN);
|
||||
+
|
||||
+ assertFalse(badItemStack.isRepairableBy(new ItemStack(Material.DIAMOND)), "acacia wall sign is repairable by diamond");
|
||||
+ }
|
||||
+}
|
||||
|
@ -830,7 +830,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708acad8a05 100644
|
||||
index 8cfce9c557c4411914adffd10872bf3129435423..62d615a4c7acfbd970278531e1bbceb71591f7b1 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
@@ -182,9 +182,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
@ -846,6 +846,15 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
|
||||
<T> Applicator put(ItemMetaKeyType<T> key, T value) {
|
||||
this.builder.set(key.TYPE, value);
|
||||
@@ -278,7 +279,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
private CraftFoodComponent food;
|
||||
private CraftToolComponent tool;
|
||||
private CraftJukeboxComponent jukebox;
|
||||
- private int damage;
|
||||
+ private Integer damage; // Paper - may not be set
|
||||
private Integer maxDamage;
|
||||
|
||||
private static final Set<DataComponentType> HANDLED_TAGS = Sets.newHashSet();
|
||||
@@ -310,7 +311,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
this.enchantments = new EnchantmentMap(meta.enchantments); // Paper
|
||||
}
|
||||
@ -876,6 +885,15 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
}
|
||||
|
||||
for (Object obj : mods.keySet()) {
|
||||
@@ -905,7 +911,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
itemTag.put(CraftMetaItem.JUKEBOX_PLAYABLE, this.jukebox.getHandle());
|
||||
}
|
||||
|
||||
- if (this.hasDamage()) {
|
||||
+ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage
|
||||
itemTag.put(CraftMetaItem.DAMAGE, this.damage);
|
||||
}
|
||||
|
||||
@@ -970,10 +976,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
}
|
||||
|
||||
@ -889,6 +907,15 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1010,7 +1014,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
|
||||
@Overridden
|
||||
boolean isEmpty() {
|
||||
- return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper
|
||||
+ return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamageValue() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper
|
||||
}
|
||||
|
||||
// Paper start
|
||||
@@ -1106,6 +1110,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
|
||||
@Override
|
||||
@ -1035,7 +1062,19 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
for (Map.Entry<Attribute, AttributeModifier> entry : first.entries()) {
|
||||
if (!second.containsEntry(entry.getKey(), entry.getValue())) {
|
||||
return false;
|
||||
@@ -1616,6 +1631,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
@@ -1606,19 +1621,33 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
|
||||
@Override
|
||||
public boolean hasDamage() {
|
||||
- return this.damage > 0;
|
||||
+ return this.damage != null && this.damage > 0; // Paper - null check
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDamage() {
|
||||
- return this.damage;
|
||||
+ return this.damage == null ? 0 : this.damage; // Paper - null check
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDamage(int damage) {
|
||||
@ -1044,7 +1083,22 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
this.damage = damage;
|
||||
}
|
||||
|
||||
@@ -1632,6 +1649,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
+ // Paper start - preserve empty/0 damage
|
||||
+ @Override
|
||||
+ public boolean hasDamageValue() {
|
||||
+ return this.damage != null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void resetDamage() {
|
||||
+ this.damage = null;
|
||||
+ }
|
||||
+ // Paper end - preserve empty/0 damage
|
||||
+
|
||||
@Override
|
||||
public boolean hasMaxDamage() {
|
||||
return this.maxDamage != null;
|
||||
@@ -1632,6 +1661,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
|
||||
@Override
|
||||
public void setMaxDamage(Integer maxDamage) {
|
||||
@ -1052,7 +1106,7 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
this.maxDamage = maxDamage;
|
||||
}
|
||||
|
||||
@@ -1663,7 +1681,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
@@ -1663,7 +1693,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
&& (this.hasCustomModelData() ? that.hasCustomModelData() && this.customModelData.equals(that.customModelData) : !that.hasCustomModelData())
|
||||
&& (this.hasBlockData() ? that.hasBlockData() && this.blockData.equals(that.blockData) : !that.hasBlockData())
|
||||
&& (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost())
|
||||
@ -1061,18 +1115,29 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
&& (this.unhandledTags.equals(that.unhandledTags))
|
||||
&& (this.removedTags.equals(that.removedTags))
|
||||
&& (Objects.equals(this.customTag, that.customTag))
|
||||
@@ -1725,8 +1743,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
@@ -1678,7 +1708,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
&& (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood())
|
||||
&& (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool())
|
||||
&& (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable())
|
||||
- && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage())
|
||||
+ && (Objects.equals(this.damage, that.damage)) // Paper - preserve empty/0 damage
|
||||
&& (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage())
|
||||
&& (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper
|
||||
&& (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper
|
||||
@@ -1724,9 +1754,9 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0);
|
||||
hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0);
|
||||
hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0);
|
||||
hash = 61 * hash + (this.hasDamage() ? this.damage : 0);
|
||||
- hash = 61 * hash + (this.hasDamage() ? this.damage : 0);
|
||||
- hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237);
|
||||
- hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0);
|
||||
+ hash = 61 * hash + (this.hasDamageValue() ? this.damage : -1); // Paper - preserve empty/0 damage
|
||||
+ hash = 61 * hash + (this.hasMaxDamage() ? this.maxDamage.hashCode() : 0); // Paper - max damage is not a boolean
|
||||
+ hash = 61 * hash + (this.attributeModifiers != null ? this.attributeModifiers.hashCode() : 0); // Paper - track only null attributes
|
||||
hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper
|
||||
hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper
|
||||
hash = 61 * hash + this.version;
|
||||
@@ -1746,7 +1764,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
@@ -1746,7 +1776,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
if (this.enchantments != null) {
|
||||
clone.enchantments = new EnchantmentMap(this.enchantments); // Paper
|
||||
}
|
||||
@ -1081,7 +1146,16 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers);
|
||||
}
|
||||
if (this.customTag != null) {
|
||||
@@ -1975,7 +1993,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
@@ -1874,7 +1904,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
builder.put(CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, this.jukebox);
|
||||
}
|
||||
|
||||
- if (this.hasDamage()) {
|
||||
+ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage
|
||||
builder.put(CraftMetaItem.DAMAGE.BUKKIT, this.damage);
|
||||
}
|
||||
|
||||
@@ -1975,7 +2005,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
}
|
||||
|
||||
static void serializeModifiers(Multimap<Attribute, AttributeModifier> modifiers, ImmutableMap.Builder<String, Object> builder, ItemMetaKey key) {
|
||||
@ -1090,7 +1164,7 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2057,7 +2075,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
@@ -2057,7 +2087,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
// Paper start - improve checking handled tags
|
||||
@org.jetbrains.annotations.VisibleForTesting
|
||||
public static final Map<Class<? extends CraftMetaItem>, Set<DataComponentType<?>>> HANDLED_DCTS_PER_TYPE = new HashMap<>();
|
||||
@ -1099,7 +1173,7 @@ index 8cfce9c557c4411914adffd10872bf3129435423..d9d4b983672b4340df926d98a7fa6708
|
||||
CraftMetaItem.NAME.TYPE,
|
||||
CraftMetaItem.ITEM_NAME.TYPE,
|
||||
CraftMetaItem.LORE.TYPE,
|
||||
@@ -2125,7 +2143,12 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
@@ -2125,7 +2155,12 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
// Paper end - improve checking handled data component types
|
||||
|
||||
protected static <T> Optional<? extends T> getOrEmpty(DataComponentPatch tag, ItemMetaKeyType<T> type) {
|
||||
|
@ -32,7 +32,7 @@ index 9d74577af071954e1e37201a96368c1360076209..eafa54c870c3e2aef30c3f9f96f51660
|
||||
throw new IllegalArgumentException("Not implemented. This is a bug");
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
index d9d4b983672b4340df926d98a7fa6708acad8a05..7c6d4c08cf07da18b414773dfed5704926938bea 100644
|
||||
index 62d615a4c7acfbd970278531e1bbceb71591f7b1..4d97024bb05ab815409fc25c5924903868cc3945 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
@@ -1452,7 +1452,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
|
300
patches/server/1024-Proxy-ItemStack-to-CraftItemStack.patch
Normale Datei
300
patches/server/1024-Proxy-ItemStack-to-CraftItemStack.patch
Normale Datei
@ -0,0 +1,300 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Tue, 14 May 2024 11:57:43 -0700
|
||||
Subject: [PATCH] Proxy ItemStack to CraftItemStack
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
index be36336a3c7d1ae88277f4ee1be70075001de7a7..814e8ece6821e359b504e8c4d140cc38700f2abe 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
@@ -25,15 +25,57 @@ import org.bukkit.material.MaterialData;
|
||||
@DelegateDeserialization(ItemStack.class)
|
||||
public final class CraftItemStack extends ItemStack {
|
||||
|
||||
- // Paper start - MC Utils
|
||||
- public static net.minecraft.world.item.ItemStack unwrap(ItemStack bukkit) {
|
||||
- if (bukkit instanceof CraftItemStack craftItemStack) {
|
||||
- return craftItemStack.handle != null ? craftItemStack.handle : net.minecraft.world.item.ItemStack.EMPTY;
|
||||
+ // Paper start - delegate api-ItemStack to CraftItemStack
|
||||
+ private static final java.lang.invoke.VarHandle API_ITEM_STACK_CRAFT_DELEGATE_FIELD;
|
||||
+ static {
|
||||
+ try {
|
||||
+ API_ITEM_STACK_CRAFT_DELEGATE_FIELD = java.lang.invoke.MethodHandles.privateLookupIn(
|
||||
+ ItemStack.class,
|
||||
+ java.lang.invoke.MethodHandles.lookup()
|
||||
+ ).findVarHandle(ItemStack.class, "craftDelegate", ItemStack.class);
|
||||
+ } catch (final IllegalAccessException | NoSuchFieldException exception) {
|
||||
+ throw new RuntimeException(exception);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static CraftItemStack getCraftStack(final ItemStack bukkit) {
|
||||
+ if (bukkit instanceof final CraftItemStack craftItemStack) {
|
||||
+ return craftItemStack;
|
||||
} else {
|
||||
- return asNMSCopy(bukkit);
|
||||
+ return (CraftItemStack) API_ITEM_STACK_CRAFT_DELEGATE_FIELD.get(bukkit);
|
||||
}
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ if (this.handle == null || this.handle.isEmpty()) {
|
||||
+ return net.minecraft.world.item.ItemStack.EMPTY.hashCode();
|
||||
+ } else {
|
||||
+ int hash = net.minecraft.world.item.ItemStack.hashItemAndComponents(this.handle);
|
||||
+ hash = hash * 31 + this.handle.getCount();
|
||||
+ return hash;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(final Object obj) {
|
||||
+ if (!(obj instanceof final org.bukkit.inventory.ItemStack bukkit)) return false;
|
||||
+ final CraftItemStack craftStack = getCraftStack(bukkit);
|
||||
+ if (this.handle == craftStack.handle) return true;
|
||||
+ else if (this.handle == null || craftStack.handle == null) return false;
|
||||
+ else if (this.handle.isEmpty() && craftStack.handle.isEmpty()) return true;
|
||||
+ else return net.minecraft.world.item.ItemStack.matches(this.handle, craftStack.handle);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ // Paper start - MC Utils
|
||||
+ public static net.minecraft.world.item.ItemStack unwrap(ItemStack bukkit) {
|
||||
+ // Paper start - re-implement after delegating all api ItemStack calls to CraftItemStack
|
||||
+ final CraftItemStack craftItemStack = getCraftStack(bukkit);
|
||||
+ return craftItemStack.handle == null ? net.minecraft.world.item.ItemStack.EMPTY : craftItemStack.handle;
|
||||
+ // Paper end - re-implement after delegating all api ItemStack calls to CraftItemStack
|
||||
+ }
|
||||
+
|
||||
public static net.minecraft.world.item.ItemStack getOrCloneOnMutation(ItemStack old, ItemStack newInstance) {
|
||||
return old == newInstance ? unwrap(old) : asNMSCopy(newInstance);
|
||||
}
|
||||
@@ -47,25 +89,13 @@ public final class CraftItemStack extends ItemStack {
|
||||
// Paper end - override isEmpty to use vanilla's impl
|
||||
|
||||
public static net.minecraft.world.item.ItemStack asNMSCopy(ItemStack original) {
|
||||
- if (original instanceof CraftItemStack) {
|
||||
- CraftItemStack stack = (CraftItemStack) original;
|
||||
- return stack.handle == null ? net.minecraft.world.item.ItemStack.EMPTY : stack.handle.copy();
|
||||
- }
|
||||
- if (original == null || original.isEmpty()) { // Paper - override isEmpty to use vanilla's impl; use isEmpty
|
||||
+ // Paper start - re-implement after delegating all api ItemStack calls to CraftItemStack
|
||||
+ if (original == null || original.isEmpty()) {
|
||||
return net.minecraft.world.item.ItemStack.EMPTY;
|
||||
}
|
||||
-
|
||||
- Item item = CraftItemType.bukkitToMinecraft(original.getType());
|
||||
-
|
||||
- if (item == null) {
|
||||
- return net.minecraft.world.item.ItemStack.EMPTY;
|
||||
- }
|
||||
-
|
||||
- net.minecraft.world.item.ItemStack stack = new net.minecraft.world.item.ItemStack(item, original.getAmount());
|
||||
- if (original.hasItemMeta()) {
|
||||
- CraftItemStack.setItemMeta(stack, original.getItemMeta());
|
||||
- }
|
||||
- return stack;
|
||||
+ final CraftItemStack stack = getCraftStack(original);
|
||||
+ return stack.handle == null ? net.minecraft.world.item.ItemStack.EMPTY : stack.handle.copy();
|
||||
+ // Paper end - re-implement after delegating all api ItemStack calls to CraftItemStack
|
||||
}
|
||||
|
||||
// Paper start
|
||||
@@ -88,14 +118,10 @@ public final class CraftItemStack extends ItemStack {
|
||||
* Copies the NMS stack to return as a strictly-Bukkit stack
|
||||
*/
|
||||
public static ItemStack asBukkitCopy(net.minecraft.world.item.ItemStack original) {
|
||||
- if (original.isEmpty()) {
|
||||
- return new ItemStack(Material.AIR);
|
||||
- }
|
||||
- ItemStack stack = new ItemStack(CraftItemType.minecraftToBukkit(original.getItem()), original.getCount());
|
||||
- if (CraftItemStack.hasItemMeta(original)) {
|
||||
- stack.setItemMeta(CraftItemStack.getItemMeta(original));
|
||||
- }
|
||||
- return stack;
|
||||
+ // Paper start - no such thing as a "strictly-Bukkit stack" anymore
|
||||
+ // we copy the stack since it should be a complete copy not a mirror
|
||||
+ return asCraftMirror(original.copy());
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public static CraftItemStack asCraftMirror(net.minecraft.world.item.ItemStack original) {
|
||||
@@ -313,11 +339,7 @@ public final class CraftItemStack extends ItemStack {
|
||||
|
||||
@Override
|
||||
public CraftItemStack clone() {
|
||||
- CraftItemStack itemStack = (CraftItemStack) super.clone();
|
||||
- if (this.handle != null) {
|
||||
- itemStack.handle = this.handle.copy();
|
||||
- }
|
||||
- return itemStack;
|
||||
+ return new org.bukkit.craftbukkit.inventory.CraftItemStack(this.handle != null ? this.handle.copy() : null); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -420,22 +442,14 @@ public final class CraftItemStack extends ItemStack {
|
||||
if (stack == this) {
|
||||
return true;
|
||||
}
|
||||
- if (!(stack instanceof CraftItemStack)) {
|
||||
- return stack.getClass() == ItemStack.class && stack.isSimilar(this);
|
||||
- }
|
||||
-
|
||||
- CraftItemStack that = (CraftItemStack) stack;
|
||||
+ final CraftItemStack that = getCraftStack(stack); // Paper - re-implement after delegating all api ItemStack calls to CraftItemStack
|
||||
if (this.handle == that.handle) {
|
||||
return true;
|
||||
}
|
||||
if (this.handle == null || that.handle == null) {
|
||||
return false;
|
||||
}
|
||||
- Material comparisonType = CraftLegacy.fromLegacy(that.getType()); // This may be called from legacy item stacks, try to get the right material
|
||||
- if (!(comparisonType == this.getType() && this.getDurability() == that.getDurability())) {
|
||||
- return false;
|
||||
- }
|
||||
- return this.hasItemMeta() ? that.hasItemMeta() && this.handle.getComponents().equals(that.handle.getComponents()) : !that.hasItemMeta();
|
||||
+ return net.minecraft.world.item.ItemStack.isSameItemSameComponents(this.handle, that.handle); // Paper - re-implement after delegating all api ItemStack calls to CraftItemStack
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java
|
||||
index 9d2feff3df87cfeefe7105d954854af05cef6f69..07539ebfefa3352de5ee7a17f2724cf2c979f399 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java
|
||||
@@ -100,13 +100,14 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack createItemStack(final int amount, @Nullable final Consumer<? super M> metaConfigurator) {
|
||||
- final ItemStack itemStack = new ItemStack(this.asMaterial(), amount);
|
||||
+ // Paper start - re-implement to return CraftItemStack
|
||||
+ final net.minecraft.world.item.ItemStack stack = new net.minecraft.world.item.ItemStack(this.item, amount);
|
||||
+ final CraftItemStack mirror = CraftItemStack.asCraftMirror(stack);
|
||||
if (metaConfigurator != null) {
|
||||
- final ItemMeta itemMeta = itemStack.getItemMeta();
|
||||
- metaConfigurator.accept((M) itemMeta);
|
||||
- itemStack.setItemMeta(itemMeta);
|
||||
+ mirror.editMeta(this.getItemMetaClass(), metaConfigurator);
|
||||
}
|
||||
- return itemStack;
|
||||
+ return mirror;
|
||||
+ // Paper start - reimplement to return CraftItemStack
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
|
||||
index 9c004e7cb46841d874ab997bf2e3b63ae763aec7..d7c8f26b21276d9ff1d5c7c9738cc1126ce7d4b9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
|
||||
@@ -678,4 +678,16 @@ public class MaterialRerouting {
|
||||
return itemStack.withType(material);
|
||||
}
|
||||
// Paper end - register paper API specific material consumers in rerouting
|
||||
+
|
||||
+ // Paper start - methods added post 1.13, no-op
|
||||
+ @RerouteStatic("org/bukkit/inventory/ItemStack")
|
||||
+ public static ItemStack of(final Material material) {
|
||||
+ return ItemStack.of(material);
|
||||
+ }
|
||||
+
|
||||
+ @RerouteStatic("org/bukkit/inventory/ItemStack")
|
||||
+ public static ItemStack of(final Material material, final int amount) {
|
||||
+ return ItemStack.of(material, amount);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 8dba6c4a2e1f305cf576e8bfdca5d0c07ab871ae..d70c5546c8bd6f364fad9b24880b6867efdab644 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -700,6 +700,13 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
}
|
||||
// Paper end - hack to get tags for non server-backed registries
|
||||
|
||||
+ // Paper start - proxy ItemStack
|
||||
+ @Override
|
||||
+ public org.bukkit.inventory.ItemStack createEmptyStack() {
|
||||
+ return CraftItemStack.asCraftMirror(null);
|
||||
+ }
|
||||
+ // Paper end - proxy ItemStack
|
||||
+
|
||||
/**
|
||||
* This helper class represents the different NBT Tags.
|
||||
* <p>
|
||||
diff --git a/src/test/java/io/papermc/paper/configuration/ConfigurationSectionTest.java b/src/test/java/io/papermc/paper/configuration/ConfigurationSectionTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e5c2fb160e9d390cdfa0259a3feb9f488b2dc14d
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/configuration/ConfigurationSectionTest.java
|
||||
@@ -0,0 +1,53 @@
|
||||
+package io.papermc.paper.configuration;
|
||||
+
|
||||
+import org.bukkit.Material;
|
||||
+import org.bukkit.configuration.ConfigurationSection;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.bukkit.support.AbstractTestingBase;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
+import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
+
|
||||
+public abstract class ConfigurationSectionTest extends AbstractTestingBase {
|
||||
+ public abstract ConfigurationSection getConfigurationSection();
|
||||
+
|
||||
+ @Test
|
||||
+ public void testGetItemStack_String() {
|
||||
+ ConfigurationSection section = getConfigurationSection();
|
||||
+ String key = "exists";
|
||||
+ ItemStack value = new ItemStack(Material.ACACIA_WOOD, 50);
|
||||
+
|
||||
+ section.set(key, value);
|
||||
+
|
||||
+ assertEquals(value, section.getItemStack(key));
|
||||
+ assertNull(section.getString("doesntExist"));
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testGetItemStack_String_ItemStack() {
|
||||
+ ConfigurationSection section = getConfigurationSection();
|
||||
+ String key = "exists";
|
||||
+ ItemStack value = new ItemStack(Material.ACACIA_WOOD, 50);
|
||||
+ ItemStack def = new ItemStack(Material.STONE, 1);
|
||||
+
|
||||
+ section.set(key, value);
|
||||
+
|
||||
+ assertEquals(value, section.getItemStack(key, def));
|
||||
+ assertEquals(def, section.getItemStack("doesntExist", def));
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testIsItemStack() {
|
||||
+ ConfigurationSection section = getConfigurationSection();
|
||||
+ String key = "exists";
|
||||
+ ItemStack value = new ItemStack(Material.ACACIA_WOOD, 50);
|
||||
+
|
||||
+ section.set(key, value);
|
||||
+
|
||||
+ assertTrue(section.isItemStack(key));
|
||||
+ assertFalse(section.isItemStack("doesntExist"));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/test/java/io/papermc/paper/configuration/MemorySectionTest.java b/src/test/java/io/papermc/paper/configuration/MemorySectionTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..def33c36f207a4c5306b5a895336aa70335c1678
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/configuration/MemorySectionTest.java
|
||||
@@ -0,0 +1,11 @@
|
||||
+package io.papermc.paper.configuration;
|
||||
+
|
||||
+import org.bukkit.configuration.ConfigurationSection;
|
||||
+import org.bukkit.configuration.MemoryConfiguration;
|
||||
+
|
||||
+public class MemorySectionTest extends ConfigurationSectionTest {
|
||||
+ @Override
|
||||
+ public ConfigurationSection getConfigurationSection() {
|
||||
+ return new MemoryConfiguration().createSection("section");
|
||||
+ }
|
||||
+}
|
@ -0,0 +1,266 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 12 Jun 2024 10:29:40 -0700
|
||||
Subject: [PATCH] Make a PDC view accessible directly from ItemStack
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/persistence/PaperPersistentDataContainerView.java b/src/main/java/io/papermc/paper/persistence/PaperPersistentDataContainerView.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fac401280d3f3689b00e16c19155ca753faa06e0
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/persistence/PaperPersistentDataContainerView.java
|
||||
@@ -0,0 +1,86 @@
|
||||
+package io.papermc.paper.persistence;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import java.io.ByteArrayOutputStream;
|
||||
+import java.io.DataOutputStream;
|
||||
+import java.io.IOException;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.nbt.NbtIo;
|
||||
+import net.minecraft.nbt.Tag;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataAdapterContext;
|
||||
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry;
|
||||
+import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
+import org.bukkit.persistence.PersistentDataType;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public abstract class PaperPersistentDataContainerView implements PersistentDataContainerView {
|
||||
+
|
||||
+ protected final CraftPersistentDataTypeRegistry registry;
|
||||
+ protected final CraftPersistentDataAdapterContext adapterContext;
|
||||
+
|
||||
+ public PaperPersistentDataContainerView(final CraftPersistentDataTypeRegistry registry) {
|
||||
+ this.registry = registry;
|
||||
+ this.adapterContext = new CraftPersistentDataAdapterContext(this.registry);
|
||||
+ }
|
||||
+
|
||||
+ public abstract @Nullable Tag getTag(final String key);
|
||||
+
|
||||
+ public abstract CompoundTag toTagCompound();
|
||||
+
|
||||
+ @Override
|
||||
+ public <P, C> boolean has(final NamespacedKey key, final PersistentDataType<P, C> type) {
|
||||
+ Preconditions.checkArgument(key != null, "The NamespacedKey key cannot be null");
|
||||
+ Preconditions.checkArgument(type != null, "The provided type cannot be null");
|
||||
+
|
||||
+ final @Nullable Tag value = this.getTag(key.toString());
|
||||
+ if (value == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return this.registry.isInstanceOf(type, value);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean has(final NamespacedKey key) {
|
||||
+ Preconditions.checkArgument(key != null, "The provided key for the custom value was null"); // Paper
|
||||
+ return this.getTag(key.toString()) != null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <P, C> @Nullable C get(final NamespacedKey key, final PersistentDataType<P, C> type) {
|
||||
+ Preconditions.checkArgument(key != null, "The NamespacedKey key cannot be null");
|
||||
+ Preconditions.checkArgument(type != null, "The provided type cannot be null");
|
||||
+
|
||||
+ final @Nullable Tag value = this.getTag(key.toString());
|
||||
+ if (value == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ return type.fromPrimitive(this.registry.extract(type, value), this.adapterContext);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <P, C> C getOrDefault(final NamespacedKey key, final PersistentDataType<P, C> type, final C defaultValue) {
|
||||
+ final C c = this.get(key, type);
|
||||
+ return c != null ? c : defaultValue;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public PersistentDataAdapterContext getAdapterContext() {
|
||||
+ return this.adapterContext;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public byte[] serializeToBytes() throws IOException {
|
||||
+ final net.minecraft.nbt.CompoundTag root = this.toTagCompound();
|
||||
+ final ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream();
|
||||
+ try (final DataOutputStream dataOutput = new DataOutputStream(byteArrayOutput)) {
|
||||
+ NbtIo.write(root, dataOutput);
|
||||
+ return byteArrayOutput.toByteArray();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
index 814e8ece6821e359b504e8c4d140cc38700f2abe..32a41c8b324aad67b9dcf74387aef299e6478a64 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
@@ -480,4 +480,63 @@ public final class CraftItemStack extends ItemStack {
|
||||
return mirrored;
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Paper start - pdc
|
||||
+ private net.minecraft.nbt.CompoundTag getPdcTag() {
|
||||
+ if (this.handle == null) {
|
||||
+ return new net.minecraft.nbt.CompoundTag();
|
||||
+ }
|
||||
+ final net.minecraft.world.item.component.CustomData customData = this.handle.getOrDefault(DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY);
|
||||
+ // getUnsafe is OK here because we are only ever *reading* the data so immutability is preserved
|
||||
+ //noinspection deprecation
|
||||
+ return customData.getUnsafe().getCompound("PublicBukkitValues");
|
||||
+ }
|
||||
+
|
||||
+ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
+ private final io.papermc.paper.persistence.PaperPersistentDataContainerView pdcView = new io.papermc.paper.persistence.PaperPersistentDataContainerView(REGISTRY) {
|
||||
+
|
||||
+ @Override
|
||||
+ public net.minecraft.nbt.CompoundTag toTagCompound() {
|
||||
+ return CraftItemStack.this.getPdcTag();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public net.minecraft.nbt.Tag getTag(final String key) {
|
||||
+ return CraftItemStack.this.getPdcTag().get(key);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.Set<org.bukkit.NamespacedKey> getKeys() {
|
||||
+ java.util.Set<org.bukkit.NamespacedKey> keys = new java.util.HashSet<>();
|
||||
+ CraftItemStack.this.getPdcTag().getAllKeys().forEach(key -> {
|
||||
+ final String[] keyData = key.split(":", 2);
|
||||
+ if (keyData.length == 2) {
|
||||
+ keys.add(new org.bukkit.NamespacedKey(keyData[0], keyData[1]));
|
||||
+ }
|
||||
+ });
|
||||
+ return java.util.Collections.unmodifiableSet(keys);
|
||||
+ };
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isEmpty() {
|
||||
+ return CraftItemStack.this.getPdcTag().isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void copyTo(final org.bukkit.persistence.PersistentDataContainer other, final boolean replace) {
|
||||
+ Preconditions.checkArgument(other != null, "The target container cannot be null");
|
||||
+ final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer target = (org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer) other;
|
||||
+ final net.minecraft.nbt.CompoundTag pdcTag = org.bukkit.craftbukkit.inventory.CraftItemStack.this.getPdcTag();
|
||||
+ for (final String key : pdcTag.getAllKeys()) {
|
||||
+ if (replace || !target.getRaw().containsKey(key)) {
|
||||
+ target.getRaw().put(key, pdcTag.get(key).copy());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+ @Override
|
||||
+ public io.papermc.paper.persistence.PersistentDataContainerView getPersistentDataContainer() {
|
||||
+ return this.pdcView;
|
||||
+ }
|
||||
+ // Paper end - pdc
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
index f55fdd57ced259ad5a95878840e98ffaa3db2e05..9d867f1659433ea15f281c8b441db7e339013100 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
@@ -16,11 +16,10 @@ import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
-public class CraftPersistentDataContainer implements PersistentDataContainer {
|
||||
+public class CraftPersistentDataContainer extends io.papermc.paper.persistence.PaperPersistentDataContainerView implements PersistentDataContainer { // Paper - split up view and mutable
|
||||
|
||||
private final Map<String, Tag> customDataTags = new HashMap<>();
|
||||
- private final CraftPersistentDataTypeRegistry registry;
|
||||
- private final CraftPersistentDataAdapterContext adapterContext;
|
||||
+ // Paper - move to PersistentDataContainerView
|
||||
|
||||
public CraftPersistentDataContainer(Map<String, Tag> customTags, CraftPersistentDataTypeRegistry registry) {
|
||||
this(registry);
|
||||
@@ -28,10 +27,15 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
|
||||
}
|
||||
|
||||
public CraftPersistentDataContainer(CraftPersistentDataTypeRegistry registry) {
|
||||
- this.registry = registry;
|
||||
- this.adapterContext = new CraftPersistentDataAdapterContext(this.registry);
|
||||
+ super(registry); // Paper - move to PersistentDataContainerView
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public Tag getTag(final String key) {
|
||||
+ return this.customDataTags.get(key);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public <T, Z> void set(@NotNull NamespacedKey key, @NotNull PersistentDataType<T, Z> type, @NotNull Z value) {
|
||||
@@ -42,44 +46,7 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
|
||||
this.customDataTags.put(key.toString(), this.registry.wrap(type, type.toPrimitive(value, this.adapterContext)));
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public <T, Z> boolean has(@NotNull NamespacedKey key, @NotNull PersistentDataType<T, Z> type) {
|
||||
- Preconditions.checkArgument(key != null, "The NamespacedKey key cannot be null");
|
||||
- Preconditions.checkArgument(type != null, "The provided type cannot be null");
|
||||
-
|
||||
- Tag value = this.customDataTags.get(key.toString());
|
||||
- if (value == null) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- return this.registry.isInstanceOf(type, value);
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public boolean has(NamespacedKey key) {
|
||||
- Preconditions.checkArgument(key != null, "The provided key for the custom value was null"); // Paper
|
||||
- return this.customDataTags.get(key.toString()) != null;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public <T, Z> Z get(@NotNull NamespacedKey key, @NotNull PersistentDataType<T, Z> type) {
|
||||
- Preconditions.checkArgument(key != null, "The NamespacedKey key cannot be null");
|
||||
- Preconditions.checkArgument(type != null, "The provided type cannot be null");
|
||||
-
|
||||
- Tag value = this.customDataTags.get(key.toString());
|
||||
- if (value == null) {
|
||||
- return null;
|
||||
- }
|
||||
-
|
||||
- return type.fromPrimitive(this.registry.extract(type, value), this.adapterContext);
|
||||
- }
|
||||
-
|
||||
- @NotNull
|
||||
- @Override
|
||||
- public <T, Z> Z getOrDefault(@NotNull NamespacedKey key, @NotNull PersistentDataType<T, Z> type, @NotNull Z defaultValue) {
|
||||
- Z z = this.get(key, type);
|
||||
- return z != null ? z : defaultValue;
|
||||
- }
|
||||
+ // Paper - move to PersistentDataContainerView
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -186,16 +153,7 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
|
||||
// Paper end
|
||||
|
||||
// Paper start - byte array serialization
|
||||
- @Override
|
||||
- public byte[] serializeToBytes() throws java.io.IOException {
|
||||
- final net.minecraft.nbt.CompoundTag root = this.toTagCompound();
|
||||
- final java.io.ByteArrayOutputStream byteArrayOutput = new java.io.ByteArrayOutputStream();
|
||||
- try (final java.io.DataOutputStream dataOutput = new java.io.DataOutputStream(byteArrayOutput)) {
|
||||
- net.minecraft.nbt.NbtIo.write(root, dataOutput);
|
||||
- return byteArrayOutput.toByteArray();
|
||||
- }
|
||||
- }
|
||||
-
|
||||
+ // Paper - move to PersistentDataContainerView
|
||||
@Override
|
||||
public void readFromBytes(final byte[] bytes, final boolean clear) throws java.io.IOException {
|
||||
if (clear) {
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren