mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-21 18:15:54 +01:00
Add ItemStack array serialization methods (#10387)
This commit is contained in:
parent
1cb2bf466f
commit
81d94483a2
@ -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 <nassim@njahnke.dev>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -50,7 +52,126 @@ index e9c29fc1db686b80bc2477d78ec2b361b8600b9e..4b4c364dad70126dee17aabca2c3da9f
|
||||
+ public byte[] serializeAsBytes() {
|
||||
+ 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 {
|
||||
|
||||
/**
|
||||
|
@ -526,7 +526,7 @@ index 5bd252c0ae3b09fe141d131360c67bb9bfbf5422..78587d9fabe6371a23a7963917b054db
|
||||
+
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index 4b4c364dad70126dee17aabca2c3da9f148dd6d0..ef36a696f2f926d70c5d93ce08f75fa9a749e32f 100644
|
||||
index 5707d038bdc41448bca7d6ebf4ef5b378809f5a8..69e7cbe49ff2388dea0214f6cb26f36f29ec1453 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;
|
||||
@ -546,7 +546,7 @@ index 4b4c364dad70126dee17aabca2c3da9f148dd6d0..ef36a696f2f926d70c5d93ce08f75fa9
|
||||
public String getTranslationKey() {
|
||||
return Bukkit.getUnsafe().getTranslationKey(this);
|
||||
}
|
||||
@@ -895,5 +896,16 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
@@ -982,5 +983,16 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
ItemMeta itemMeta = getItemMeta();
|
||||
return itemMeta != null && itemMeta.hasItemFlag(flag);
|
||||
}
|
||||
|
@ -110,10 +110,10 @@ index e7931f73f10fe35ebd5fe4a04b036d53bb117ebd..cbce835ed6d44e5b8c9aaae4e36a77f8
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index ef36a696f2f926d70c5d93ce08f75fa9a749e32f..fb1d7ff51f267225ac76c29a56d67fb443d3a92f 100644
|
||||
index 69e7cbe49ff2388dea0214f6cb26f36f29ec1453..d2af613c56010f3b0dd0d3ff7b438193127353d0 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -907,5 +907,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
@@ -994,5 +994,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
public @NotNull String translationKey() {
|
||||
return Bukkit.getUnsafe().getTranslationKey(this);
|
||||
}
|
||||
|
@ -25,10 +25,10 @@ index 51473ffbec65a2344449daa8ff5cf535b0b60520..07669aad6d9910174fbc8fdf3cdd5421
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index fb1d7ff51f267225ac76c29a56d67fb443d3a92f..b38154b45935ec45154e89277a8c2b1b9e46522d 100644
|
||||
index d2af613c56010f3b0dd0d3ff7b438193127353d0..5b84aec2897b35da3e1bee8ac73fba5c83717d5d 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -919,5 +919,27 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
@@ -1006,5 +1006,27 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
public io.papermc.paper.inventory.ItemRarity getRarity() {
|
||||
return io.papermc.paper.inventory.ItemRarity.valueOf(this.getItemMeta().getRarity().name());
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ index 86c5ceddc722d28261f8a6d8368400fe2731aaf0..9f3e2903c955f2a5d1b25825c49188df
|
||||
+ // Paper end - ItemStack damage API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index ab74890e9b6a13b76756f884d6d176bb45470191..659191a226cae406a14c67cc0992f7026f6188e6 100644
|
||||
index a20f3a0894b700c235da1b8e1481062014054585..5c02a5fe37ea09502ca6c93d637a8ef5e4392ad4 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -1003,5 +1003,19 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
@@ -1090,5 +1090,19 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
public boolean canRepair(@NotNull ItemStack toBeRepaired) {
|
||||
return Bukkit.getUnsafe().isValidRepairItemStack(toBeRepaired, this);
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ Subject: [PATCH] Allow proper checking of empty item stacks
|
||||
This adds a method to check if an item stack is empty or not. This mirrors vanilla's implementation of the same method.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index 659191a226cae406a14c67cc0992f7026f6188e6..5b918d510b9c8a6f8c6d146e90e1d0ef4a204b5a 100644
|
||||
index 5c02a5fe37ea09502ca6c93d637a8ef5e4392ad4..8ded653f2b0549ebbe1a84d50ff0f3c85ddd07b7 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -1017,5 +1017,24 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
@@ -1104,5 +1104,24 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
public @NotNull ItemStack damage(int amount, @NotNull org.bukkit.entity.LivingEntity livingEntity) {
|
||||
return livingEntity.damageItemStack(this, amount);
|
||||
}
|
||||
|
@ -119,10 +119,10 @@ index 141d5a964cc299284aecd4d34d57008a32f94247..31217b38e769f97801fa1afefeb223d1
|
||||
+ @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
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index 13d035ace9fbe93c3754595ac6cadbfbe30062a5..718070359c644de65c8fc2b34ad39913525d18c6 100644
|
||||
index 43b8823d4af93febbd60d1b16b406a665373bacd..268baface3b58fba4f7c8a4d3f1b370fa1d26cee 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -1037,4 +1037,21 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
@@ -1124,4 +1124,21 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
return type.isAir() || amount <= 0;
|
||||
}
|
||||
// Paper end
|
||||
|
@ -16,7 +16,7 @@ index 9bdba60fa96edbc4be5dcf54a815579db887048b..330e3013eda204aa9b33d5e1c3104e0b
|
||||
+ 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 1d2ffdf88daa9186993c69c5ab2b96520b41920b..4fe68a22576933676271f841a5af0ee45b90216f 100644
|
||||
index e80261e0e66e6d3969513593dbbf3d890158676c..9464c27fe536fc5765d945631215cbe90fd5fa47 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;
|
||||
@ -412,7 +412,7 @@ index 1d2ffdf88daa9186993c69c5ab2b96520b41920b..4fe68a22576933676271f841a5af0ee4
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@@ -807,11 +747,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
@@ -894,11 +834,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
}
|
||||
|
||||
public int getMaxItemUseDuration(@NotNull final org.bukkit.entity.LivingEntity entity) {
|
||||
@ -425,7 +425,7 @@ index 1d2ffdf88daa9186993c69c5ab2b96520b41920b..4fe68a22576933676271f841a5af0ee4
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1061,7 +997,8 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
@@ -1148,7 +1084,8 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
*/
|
||||
@NotNull
|
||||
public static ItemStack empty() {
|
||||
@ -435,7 +435,7 @@ index 1d2ffdf88daa9186993c69c5ab2b96520b41920b..4fe68a22576933676271f841a5af0ee4
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1069,7 +1006,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
@@ -1156,7 +1093,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
* it is either air or the stack has a size of 0.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
|
Loading…
Reference in New Issue
Block a user