From 166dc90e1cc0f370d3e60c5ef76c69543210e685 Mon Sep 17 00:00:00 2001 From: Josh Roy <10731363+JRoy@users.noreply.github.com> Date: Tue, 24 Jan 2023 09:30:51 -0500 Subject: [PATCH] Remove CraftItemStack#setAmount null assignment (#8807) This creates a problem with Paper's item serialization api where deserialized items, which are internally created as a CraftItemStack, will be completely lost if #setAmount(0) is invoked (since the underlying handle is set to null), while a regular Bukkit ItemStack simply sets the amount field to zero, retaining the item's data. Vanilla treats items with zero amounts the same as items with less than zero amounts, so this code doesn't create a problem with operations on the vanilla ItemStack. --- .../Add-Raw-Byte-Entity-Serialization.patch | 5 ++-- ...Add-Raw-Byte-ItemStack-Serialization.patch | 3 +- ...tItemStack-setAmount-null-assignment.patch | 30 +++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 patches/server/Remove-CraftItemStack-setAmount-null-assignment.patch diff --git a/patches/server/Add-Raw-Byte-Entity-Serialization.patch b/patches/server/Add-Raw-Byte-Entity-Serialization.patch index 70438a6db6..4074e099d1 100644 --- a/patches/server/Add-Raw-Byte-Entity-Serialization.patch +++ b/patches/server/Add-Raw-Byte-Entity-Serialization.patch @@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of((CompoundTag) converted.getValue())); + return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ITEM_STACK, compound, dataVersion, getDataVersion()))); } + @Override @@ -69,8 +69,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + CompoundTag compound = deserializeNbtFromBytes(data); + int dataVersion = compound.getInt("DataVersion"); -+ Dynamic converted = DataFixers.getDataFixer().update(References.ENTITY_TREE, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); -+ compound = (CompoundTag) converted.getValue(); ++ compound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY, compound, dataVersion, getDataVersion()); + if (!preserveUUID) compound.remove("UUID"); // Generate a new UUID so we don't have to worry about deserializing the same entity twice + return net.minecraft.world.entity.EntityType.create(compound, ((org.bukkit.craftbukkit.CraftWorld) world).getHandle()) + .orElseThrow(() -> new IllegalArgumentException("An ID was not found for the data. Did you downgrade?")).getBukkitEntity(); diff --git a/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch index d39f4869d4..e02614e295 100644 --- a/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch +++ b/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch @@ -29,8 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + CompoundTag compound = deserializeNbtFromBytes(data); + int dataVersion = compound.getInt("DataVersion"); -+ Dynamic converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); -+ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of((CompoundTag) converted.getValue())); ++ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ITEM_STACK, compound, dataVersion, getDataVersion()))); + } + + private byte[] serializeNbtToBytes(CompoundTag compound) { diff --git a/patches/server/Remove-CraftItemStack-setAmount-null-assignment.patch b/patches/server/Remove-CraftItemStack-setAmount-null-assignment.patch new file mode 100644 index 0000000000..6741ed5cda --- /dev/null +++ b/patches/server/Remove-CraftItemStack-setAmount-null-assignment.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josh Roy <10731363+JRoy@users.noreply.github.com> +Date: Mon, 23 Jan 2023 19:19:01 -0500 +Subject: [PATCH] Remove CraftItemStack#setAmount null assignment + +This creates a problem with Paper's item serialization +api where deserialized items, which are internally +created as a CraftItemStack, will be completely lost if +#setAmount(0) is invoked (since the underlying handle +is set to null), while a regular Bukkit ItemStack +simply sets the amount field to zero, retaining the +item's data. + +Vanilla treats items with zero amounts the same as items +with less than zero amounts, so this code doesn't create +a problem with operations on the vanilla ItemStack. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack { + } + + this.handle.setCount(amount); +- if (amount == 0) { ++ if (false && amount == 0) { // Paper - remove CraftItemStack#setAmount null assignment + this.handle = null; + } + }