Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save masmc05/9ac64195722bfb509a8a2e0b09ceea52 to your computer and use it in GitHub Desktop.
Save masmc05/9ac64195722bfb509a8a2e0b09ceea52 to your computer and use it in GitHub Desktop.
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: masmc05 <masmc05@gmail.com>
Date: Wed, 8 May 2024 17:25:31 +0300
Subject: [PATCH] Use minecraft item serialization logic
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
index a3ba9249e636d1fb8dad98fab413436009fe04df..e7150d92ed0862af7526792d43f56e0680e32c68 100644
--- a/src/main/java/org/bukkit/UnsafeValues.java
+++ b/src/main/java/org/bukkit/UnsafeValues.java
@@ -273,4 +273,8 @@ public interface UnsafeValues {
// Paper end - lifecycle event API
@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
+ // Paper start - use minecraft item serialization logic
+ @NotNull java.util.Map<String, Object> serializeItemStack(@NotNull ItemStack itemStack);
+ @NotNull ItemStack deserializeItemStack(@NotNull java.util.Map<String, Object> itemMap);
+ // Paper end - use minecraft item serialization logic
}
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
index 84a7bf0936d35bf42b5ed038d295d5c31740f472..8438a308206fb78673addda82cb3906015cf8ebf 100644
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
@@ -502,6 +502,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
@NotNull
@Utility
public Map<String, Object> serialize() {
+ if (true) return Bukkit.getUnsafe().serializeItemStack(this); // Paper - use minecraft item serialization logic
Map<String, Object> result = new LinkedHashMap<String, Object>();
result.put("v", Bukkit.getUnsafe().getDataVersion()); // Include version to indicate we are using modern material names (or LEGACY prefix)
@@ -528,6 +529,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
*/
@NotNull
public static ItemStack deserialize(@NotNull Map<String, Object> args) {
+ // Paper start - use minecraft item serialization logic
+ return Bukkit.getUnsafe().deserializeItemStack(args);
+ }
+ @NotNull
+ @Deprecated
+ public static ItemStack deserializeLegacy(@NotNull Map<String, Object> args) {
+ // Paper end - use minecraft item serialization logic
int version = (args.containsKey("v")) ? ((Number) args.get("v")).intValue() : -1;
short damage = 0;
int amount = 1;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: masmc05 <masmc05@gmail.com>
Date: Wed, 8 May 2024 17:25:30 +0300
Subject: [PATCH] Use minecraft item serialization logic
Minecraft doesn't care about specific types (like a byte instead of short) so
we can serialize to yaml without expecting breakages, while in custom data there may be
data from plugins or other sources which will expect exact type to be preserved
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index a1c9989df460d7ae3666fffe7968750832a30b85..b001c967f7998cf9b236dc6fcff6ec6b6e0d6776 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -1,15 +1,21 @@
package org.bukkit.craftbukkit.util;
+import ca.spottedleaf.dataconverter.minecraft.MCDataConverter;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import com.google.common.io.Files;
import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import com.mojang.serialization.DataResult;
import com.mojang.serialization.Dynamic;
+import com.mojang.serialization.JavaOps;
import com.mojang.serialization.JsonOps;
import java.io.File;
import java.io.IOException;
@@ -22,11 +28,14 @@ import net.minecraft.SharedConstants;
import net.minecraft.advancements.AdvancementHolder;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.item.ItemParser;
+import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
+import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
+import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ServerAdvancementManager;
@@ -34,6 +43,7 @@ import net.minecraft.util.datafix.DataFixers;
import net.minecraft.util.datafix.fixes.References;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.alchemy.Potion;
+import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.item.component.ItemAttributeModifiers;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
@@ -69,6 +79,7 @@ import org.bukkit.material.MaterialData;
import org.bukkit.plugin.InvalidPluginException;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.potion.PotionType;
+import org.jetbrains.annotations.NotNull;
@SuppressWarnings("deprecation")
public final class CraftMagicNumbers implements UnsafeValues {
@@ -673,6 +684,46 @@ public final class CraftMagicNumbers implements UnsafeValues {
return new io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEventManager<>(plugin, registrationCheck);
}
// Paper end - lifecycle event API
+ // Paper start - use minecraft item serialization logic
+ @SuppressWarnings("unchecked")
+ @Override
+ public @NotNull Map<String, Object> serializeItemStack(@NotNull ItemStack itemStack) {
+ net.minecraft.world.item.ItemStack item = CraftItemStack.unwrap(itemStack);
+ CustomData customData = item.get(DataComponents.CUSTOM_DATA);
+ item.remove(DataComponents.CUSTOM_DATA);
+ RegistryOps<Object> ops = CraftRegistry.getMinecraftRegistry().createSerializationContext(JavaOps.INSTANCE);
+ DataResult<Object> result = net.minecraft.world.item.ItemStack.CODEC.encodeStart(ops, item);
+ if (customData != null) {
+ item.set(DataComponents.CUSTOM_DATA, customData);
+ }
+ Map<String, Object> map = (Map<String, Object>) result.getOrThrow();
+ ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
+ builder.put("version", this.getDataVersion());
+ builder.putAll(map);
+ if (customData != null) {
+ builder.put("custom", CraftNBTTagConfigSerializer.serialize(customData.getUnsafe()));
+ }
+ return builder.build();
+ }
+ @Override
+ public @NotNull ItemStack deserializeItemStack(@NotNull Map<String, Object> itemMap) {
+ if (itemMap.containsKey("type")) {
+ return ItemStack.deserializeLegacy(itemMap);
+ }
+ JsonObject asJson = JavaOps.INSTANCE.convertTo(JsonOps.INSTANCE, itemMap).getAsJsonObject();
+ int version = asJson.get("version").getAsInt();
+ asJson = MCDataConverter.convertJson(MCTypeRegistry.ITEM_STACK, asJson, false, version, this.getDataVersion());
+ net.minecraft.world.item.ItemStack item = net.minecraft.world.item.ItemStack.STRICT_CODEC.parse(JsonOps.INSTANCE, asJson).getOrThrow();
+ if (asJson.has("custom")) {
+ String customData = asJson.get("custom").getAsString();
+ CompoundTag nbt = (CompoundTag) CraftNBTTagConfigSerializer.deserialize(customData);
+ if (item.has(DataComponents.CUSTOM_DATA)) {
+ nbt.merge(item.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).getUnsafe());
+ }
+ item.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
+ }
+ return CraftItemStack.asCraftMirror(item);
+ }
/**
* This helper class represents the different NBT Tags.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment