aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch')
-rw-r--r--patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch125
1 files changed, 123 insertions, 2 deletions
diff --git a/patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch
index a68554bd2a..f4750496c2 100644
--- a/patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch
+++ b/patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch
@@ -5,6 +5,8 @@ Subject: [PATCH] Add Raw Byte ItemStack Serialization
Serializes using NBT which is safer for server data migrations than bukkits format.
+Co-authored-by: Nassim Jahnke <[email protected]>
+
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
index 6e67fdb091a006d2d13bc2d93db4d55348af4c8f..e41d5d9b810c8816cd0d1eba5fd1ea56252fb0df 100644
--- a/src/main/java/org/bukkit/UnsafeValues.java
@@ -20,10 +22,10 @@ index 6e67fdb091a006d2d13bc2d93db4d55348af4c8f..e41d5d9b810c8816cd0d1eba5fd1ea56
// Paper end
}
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
-index e9c29fc1db686b80bc2477d78ec2b361b8600b9e..4b4c364dad70126dee17aabca2c3da9f148dd6d0 100644
+index e9c29fc1db686b80bc2477d78ec2b361b8600b9e..dda3a421953761dfca5f2f6498905c43fb6fe37d 100644
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
-@@ -661,6 +661,30 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
+@@ -661,6 +661,117 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
return Bukkit.getServer().getItemFactory().ensureServerConversions(this);
}
@@ -51,6 +53,125 @@ index e9c29fc1db686b80bc2477d78ec2b361b8600b9e..4b4c364dad70126dee17aabca2c3da9f
+ return org.bukkit.Bukkit.getUnsafe().serializeItem(this);
+ }
+
++ /**
++ * The current version byte of the item array format used in {@link #serializeItemsAsBytes(java.util.Collection)}
++ * and {@link #deserializeItemsFromBytes(byte[])} respectively.
++ */
++ private static final byte ARRAY_SERIALIZATION_VERSION = 1;
++
++ /**
++ * Serializes a collection of items to raw bytes in NBT. Serializes empty items as null.
++ * <p>
++ * If you need a string representation to put into a file, you can for example use {@link java.util.Base64} encoding.
++ *
++ * @param items items to serialize
++ * @return bytes representing the items in NBT
++ * @see #serializeAsBytes()
++ */
++ public static byte @NotNull [] serializeItemsAsBytes(java.util.@NotNull Collection<ItemStack> items) {
++ try (final java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream()) {
++ final java.io.DataOutput output = new java.io.DataOutputStream(outputStream);
++ output.writeByte(ARRAY_SERIALIZATION_VERSION);
++ output.writeInt(items.size());
++ for (final ItemStack item : items) {
++ if (item == null || item.isEmpty()) {
++ // Ensure the correct order by including empty/null items
++ output.writeInt(0);
++ continue;
++ }
++
++ final byte[] itemBytes = item.serializeAsBytes();
++ output.writeInt(itemBytes.length);
++ output.write(itemBytes);
++ }
++ return outputStream.toByteArray();
++ } catch (final java.io.IOException e) {
++ throw new RuntimeException("Error while writing itemstack", e);
++ }
++ }
++
++ /**
++ * Serializes a collection of items to raw bytes in NBT. Serializes empty items as null.
++ * <p>
++ * If you need a string representation to put into a file, you can for example use {@link java.util.Base64} encoding.
++ *
++ * @param items items to serialize
++ * @return bytes representing the items in NBT
++ * @see #serializeAsBytes()
++ */
++ public static byte @NotNull [] serializeItemsAsBytes(@Nullable ItemStack @NotNull [] items) {
++ return serializeItemsAsBytes(java.util.Arrays.asList(items));
++ }
++
++ /**
++ * Deserializes this itemstack from raw NBT bytes.
++ * <p>
++ * If you need a string representation to put into a file, you can for example use {@link java.util.Base64} encoding.
++ *
++ * @param bytes bytes representing an item in NBT
++ * @return ItemStack array migrated to this version of Minecraft if needed
++ * @see #deserializeBytes(byte[])
++ */
++ public static @NotNull ItemStack @NotNull [] deserializeItemsFromBytes(final byte @NotNull [] bytes) {
++ try (final java.io.ByteArrayInputStream inputStream = new java.io.ByteArrayInputStream(bytes)) {
++ final java.io.DataInputStream input = new java.io.DataInputStream(inputStream);
++ final byte version = input.readByte();
++ if (version != ARRAY_SERIALIZATION_VERSION) {
++ throw new IllegalArgumentException("Unsupported version or bad data: " + version);
++ }
++
++ final int count = input.readInt();
++ final ItemStack[] items = new ItemStack[count];
++ for (int i = 0; i < count; i++) {
++ final int length = input.readInt();
++ if (length == 0) {
++ // Empty item, keep entry as empty
++ items[i] = ItemStack.empty();
++ continue;
++ }
++
++ final byte[] itemBytes = new byte[length];
++ input.read(itemBytes);
++ items[i] = ItemStack.deserializeBytes(itemBytes);
++ }
++ return items;
++ } catch (final java.io.IOException e) {
++ throw new RuntimeException("Error while reading itemstack", e);
++ }
++ }
++
/**
* Gets the Display name as seen in the Client.
* Currently the server only supports the English language. To override this,
+diff --git a/src/main/java/org/bukkit/util/io/BukkitObjectInputStream.java b/src/main/java/org/bukkit/util/io/BukkitObjectInputStream.java
+index 0f8eb97bd5e2f8b0f0cc03f7c4342aae06c4520c..6c074ff2dcfc279657037013b9b54890d7c8a533 100644
+--- a/src/main/java/org/bukkit/util/io/BukkitObjectInputStream.java
++++ b/src/main/java/org/bukkit/util/io/BukkitObjectInputStream.java
+@@ -14,7 +14,11 @@ import org.bukkit.configuration.serialization.ConfigurationSerialization;
+ * <p>
+ * Behavior of implementations extending this class is not guaranteed across
+ * future versions.
++ * @deprecated Object streams on their own are not safe. For safer and more consistent serialization of items,
++ * use {@link org.bukkit.inventory.ItemStack#serializeAsBytes()} or
++ * {@link org.bukkit.inventory.ItemStack#serializeItemsAsBytes(java.util.Collection)}.
+ */
++@Deprecated(since = "1.21") // Paper
+ public class BukkitObjectInputStream extends ObjectInputStream {
+
+ /**
+diff --git a/src/main/java/org/bukkit/util/io/BukkitObjectOutputStream.java b/src/main/java/org/bukkit/util/io/BukkitObjectOutputStream.java
+index dd1b9ee5f57773f07924aa311823fd8d63195cb2..4e24e7c73271a579db2c4309951693dfb2fecceb 100644
+--- a/src/main/java/org/bukkit/util/io/BukkitObjectOutputStream.java
++++ b/src/main/java/org/bukkit/util/io/BukkitObjectOutputStream.java
+@@ -14,7 +14,11 @@ import org.bukkit.configuration.serialization.ConfigurationSerializable;
+ * <p>
+ * Behavior of implementations extending this class is not guaranteed across
+ * future versions.
++ * @deprecated Object streams on their own are not safe. For safer and more consistent serialization of items,
++ * use {@link org.bukkit.inventory.ItemStack#serializeAsBytes()} or
++ * {@link org.bukkit.inventory.ItemStack#serializeItemsAsBytes(java.util.Collection)}.
+ */
++@Deprecated(since = "1.21") // Paper
+ public class BukkitObjectOutputStream extends ObjectOutputStream {
+
+ /**