aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0995-Proxy-ItemStack-to-CraftItemStack.patch
diff options
context:
space:
mode:
authorNassim Jahnke <[email protected]>2024-10-27 18:11:15 +0100
committerNassim Jahnke <[email protected]>2024-10-27 18:39:30 +0100
commit02bca1e6558bf4ac0cbf928d48e90f497b10b0a3 (patch)
tree1144072e447f4c0b7e80b278fd769106227f016a /patches/server/0995-Proxy-ItemStack-to-CraftItemStack.patch
parent12ed02105177f54906a7d4422b235929426bc264 (diff)
downloadPaper-02bca1e6558bf4ac0cbf928d48e90f497b10b0a3.tar.gz
Paper-02bca1e6558bf4ac0cbf928d48e90f497b10b0a3.zip
Remove timings impl
Diffstat (limited to 'patches/server/0995-Proxy-ItemStack-to-CraftItemStack.patch')
-rw-r--r--patches/server/0995-Proxy-ItemStack-to-CraftItemStack.patch302
1 files changed, 302 insertions, 0 deletions
diff --git a/patches/server/0995-Proxy-ItemStack-to-CraftItemStack.patch b/patches/server/0995-Proxy-ItemStack-to-CraftItemStack.patch
new file mode 100644
index 0000000000..40da32a4fb
--- /dev/null
+++ b/patches/server/0995-Proxy-ItemStack-to-CraftItemStack.patch
@@ -0,0 +1,302 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jake Potrebic <[email protected]>
+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 bb2b4528692aed8e3341428697a60c0abee13779..49d2deac8d42a505b75f2196ef895a5564b62cac 100644
+--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
+@@ -31,15 +31,57 @@ import org.jetbrains.annotations.ApiStatus;
+ @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);
+ }
+@@ -53,25 +95,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
+@@ -94,14 +124,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) {
+@@ -329,11 +355,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
+@@ -436,22 +458,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 f4a6ee6dfcb2d516a9a1a9c81494b50a629110e4..96dfcfa12c63c682edcdec98647ca6a94d9fb4ed 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 6cc9d7a9e6d4bfdc27e52fc581b2bb832616f121..6930d0afb230a88aa813b02e4d55c95d3a049688 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 d728bf1d83877290e4d3fdaa7649ed077c0ee1ec..d3759c1262a5ce8ff82215a99abd31f20af95fc5 100644
+--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+@@ -673,6 +673,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..ed45bfa577579afcbd54d655c3b5d05d6c6f3e86
+--- /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.environment.VanillaFeature;
++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 {
++ 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..c00085328ce8a00fc274632a556ab27660fa57ed
+--- /dev/null
++++ b/src/test/java/io/papermc/paper/configuration/MemorySectionTest.java
+@@ -0,0 +1,13 @@
++package io.papermc.paper.configuration;
++
++import org.bukkit.configuration.ConfigurationSection;
++import org.bukkit.configuration.MemoryConfiguration;
++import org.bukkit.support.environment.Normal;
++
++@Normal
++public class MemorySectionTest extends ConfigurationSectionTest {
++ @Override
++ public ConfigurationSection getConfigurationSection() {
++ return new MemoryConfiguration().createSection("section");
++ }
++}