This commit is contained in:
Riley Park 2024-04-30 01:22:11 -07:00
parent d88a394ff9
commit fdc75fe16a
2 changed files with 217 additions and 215 deletions

View File

@ -6,10 +6,10 @@ Subject: [PATCH] WIP DataKey API
diff --git a/src/main/java/io/papermc/paper/datakey/DataComponentType.java b/src/main/java/io/papermc/paper/datakey/DataComponentType.java
new file mode 100644
index 0000000000000000000000000000000000000000..684400c5de46d79ef7506f7c8240e57b84252b94
index 0000000000000000000000000000000000000000..a3717f07970935831d949160f3a8938599c169a3
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/DataComponentType.java
@@ -0,0 +1,17 @@
@@ -0,0 +1,18 @@
+package io.papermc.paper.datakey;
+
+import net.kyori.adventure.key.Key;
@ -17,6 +17,7 @@ index 0000000000000000000000000000000000000000..684400c5de46d79ef7506f7c8240e57b
+
+public interface DataComponentType extends Keyed {
+
+ @Override
+ Key key();
+
+ interface Valued<T> extends DataComponentType {
@ -29,10 +30,10 @@ index 0000000000000000000000000000000000000000..684400c5de46d79ef7506f7c8240e57b
+}
diff --git a/src/main/java/io/papermc/paper/datakey/DataComponentTypes.java b/src/main/java/io/papermc/paper/datakey/DataComponentTypes.java
new file mode 100644
index 0000000000000000000000000000000000000000..978d4d3d28c3563d15f7566004103a898af19278
index 0000000000000000000000000000000000000000..83f396a9b427eb87c82a68bb1d3fbe7d1ca0e32b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/DataComponentTypes.java
@@ -0,0 +1,77 @@
@@ -0,0 +1,76 @@
+package io.papermc.paper.datakey;
+
+import io.papermc.paper.datakey.types.ItemLore;
@ -44,27 +45,27 @@ index 0000000000000000000000000000000000000000..978d4d3d28c3563d15f7566004103a89
+
+public class DataComponentTypes {
+
+ public static final DataComponentType.Valued<Integer> MAX_STACK_SIZE = typed("max_stack_size");
+ public static final DataComponentType.Valued<Integer> MAX_DAMAGE = typed("max_damage");
+ public static final DataComponentType.Valued<Integer> DAMAGE = typed("damage");
+ public static final DataComponentType.Valued<Unbreakable> UNBREAKABLE = typed("unbreakable");
+ public static final DataComponentType.Valued<Component> CUSTOM_NAME = typed("custom_name");
+ public static final DataComponentType.Valued<Component> ITEM_NAME = typed("item_name");
+ public static final DataComponentType.Valued<ItemLore> LORE = typed("lore");
+ public static final DataComponentType.Valued<ItemRarity> RARITY = typed("rarity");
+ public static final DataComponentType.Valued<Integer> MAX_STACK_SIZE = valued("max_stack_size");
+ public static final DataComponentType.Valued<Integer> MAX_DAMAGE = valued("max_damage");
+ public static final DataComponentType.Valued<Integer> DAMAGE = valued("damage");
+ public static final DataComponentType.Valued<Unbreakable> UNBREAKABLE = valued("unbreakable");
+ public static final DataComponentType.Valued<Component> CUSTOM_NAME = valued("custom_name");
+ public static final DataComponentType.Valued<Component> ITEM_NAME = valued("item_name");
+ public static final DataComponentType.Valued<ItemLore> LORE = valued("lore");
+ public static final DataComponentType.Valued<ItemRarity> RARITY = valued("rarity");
+ // enchantments
+ // can_place_on
+ // can_break
+ // attribute_modifiers
+ // custom_model_data
+ public static final DataComponentType.NonValued HIDE_ADDITIONAL_TOOLTIP = nonTyped("hide_additional_tooltip");
+ public static final DataComponentType.NonValued HIDE_TOOLTIP = nonTyped("hide_tooltip");
+ public static final DataComponentType.Valued<Integer> REPAIR_COST = typed("repair_cost");
+ public static final DataComponentType.NonValued CREATIVE_SLOT_LOCK = nonTyped("creative_slot_lock");
+ public static final DataComponentType.Valued<Boolean> ENCHANTMENT_GLINT_OVERRIDE = typed("enchantment_glint_override");
+ public static final DataComponentType.NonValued INTANGIBLE_PROJECTILE = nonTyped("intangible_projectile");
+ public static final DataComponentType.NonValued HIDE_ADDITIONAL_TOOLTIP = unvalued("hide_additional_tooltip");
+ public static final DataComponentType.NonValued HIDE_TOOLTIP = unvalued("hide_tooltip");
+ public static final DataComponentType.Valued<Integer> REPAIR_COST = valued("repair_cost");
+ public static final DataComponentType.NonValued CREATIVE_SLOT_LOCK = unvalued("creative_slot_lock");
+ public static final DataComponentType.Valued<Boolean> ENCHANTMENT_GLINT_OVERRIDE = valued("enchantment_glint_override");
+ public static final DataComponentType.NonValued INTANGIBLE_PROJECTILE = unvalued("intangible_projectile");
+ // food
+ public static final DataComponentType.NonValued FIRE_RESISTANT = nonTyped("fire_resistant");
+ public static final DataComponentType.NonValued FIRE_RESISTANT = unvalued("fire_resistant");
+ // tool
+ // stored_enchantments
+ // dyed_color
@ -84,7 +85,7 @@ index 0000000000000000000000000000000000000000..978d4d3d28c3563d15f7566004103a89
+ // bucket_entity_data
+ // block_entity_data
+ // instrument
+ public static final DataComponentType.Valued<Integer> OMINOUS_BOTTLE_AMPLIFIER = typed("ominous_bottle_amplifier");
+ public static final DataComponentType.Valued<Integer> OMINOUS_BOTTLE_AMPLIFIER = valued("ominous_bottle_amplifier");
+ // recipes
+ // lodestone_tracker
+ // firework_explosion
@ -100,19 +101,18 @@ index 0000000000000000000000000000000000000000..978d4d3d28c3563d15f7566004103a89
+ // lock
+ // container_loot
+
+ @SuppressWarnings("unchecked")
+ private static DataComponentType.NonValued nonTyped(String name) {
+ private static DataComponentType.NonValued unvalued(final String name) {
+ return (DataComponentType.NonValued) Registry.DATA_COMPONENT_TYPE.get(NamespacedKey.minecraft(name));
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> DataComponentType.Valued<T> typed(String name) {
+ private static <T> DataComponentType.Valued<T> valued(final String name) {
+ return (DataComponentType.Valued<T>) Registry.DATA_COMPONENT_TYPE.get(NamespacedKey.minecraft(name));
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datakey/map/DataComponentMap.java b/src/main/java/io/papermc/paper/datakey/map/DataComponentMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ca7314eef78bb74b8da5c830d6eb63e14af3a02
index 0000000000000000000000000000000000000000..441c14e660ab881cbb73a73fee4c8696594ee1d1
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/map/DataComponentMap.java
@@ -0,0 +1,31 @@
@ -134,22 +134,22 @@ index 0000000000000000000000000000000000000000..5ca7314eef78bb74b8da5c830d6eb63e
+ @Contract(pure = true)
+ <T> @Nullable T get(DataComponentType.Valued<T> type);
+
+ @Contract(pure = true)
+ @Nullable Set<DataComponentType> keySet();
+
+ @Contract(pure = true)
+ boolean has(@NotNull DataComponentType type);
+
+ @Contract(value = "_, !null -> !null", pure = true)
+ default <T> @Nullable T getOrDefault(final DataComponentType.@Nullable Valued<? extends T> type, final @Nullable T fallback) {
+ final T object = this.get(type);
+ return object != null ? object : fallback;
+ }
+
+ @Contract(pure = true)
+ boolean has(@NotNull DataComponentType type);
+
+ @Contract(pure = true)
+ Set<DataComponentType> keySet();
+
+}
diff --git a/src/main/java/io/papermc/paper/datakey/map/DataComponentPatchMapBridge.java b/src/main/java/io/papermc/paper/datakey/map/DataComponentPatchMapBridge.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0d825400f459a1aea44a7717286df7410bbbc0c
index 0000000000000000000000000000000000000000..5d60b4c1a7f2588838145001865236ce0d283c46
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/map/DataComponentPatchMapBridge.java
@@ -0,0 +1,30 @@
@ -164,15 +164,15 @@ index 0000000000000000000000000000000000000000..e0d825400f459a1aea44a7717286df74
+@ApiStatus.Internal
+public interface DataComponentPatchMapBridge {
+
+ PatchedDataComponentMap of(DataComponentMap keyMap);
+ PatchedDataComponentMap of(DataComponentMap map);
+
+ DataComponentMap empty();
+
+ DataComponentMap fromItem(Material material);
+
+ PatchedDataComponentMap fromItemMeta(Material material, ItemMeta itemMeta);
+ PatchedDataComponentMap fromItemAndMeta(Material material, ItemMeta meta);
+
+ ItemMeta toItemMeta(Material material, PatchedDataComponentMap dataKeyMap);
+ ItemMeta toItemMeta(Material material, PatchedDataComponentMap map);
+
+ @ApiStatus.Internal
+ final class Holder {
@ -185,10 +185,10 @@ index 0000000000000000000000000000000000000000..e0d825400f459a1aea44a7717286df74
+}
diff --git a/src/main/java/io/papermc/paper/datakey/map/PatchedDataComponentMap.java b/src/main/java/io/papermc/paper/datakey/map/PatchedDataComponentMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..adc0fc866fe04063c1f4a6c0bb98e416f14f8d06
index 0000000000000000000000000000000000000000..2bb4c4dbd7b5358361d6dda21c267360a1ce0e1c
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/map/PatchedDataComponentMap.java
@@ -0,0 +1,57 @@
@@ -0,0 +1,56 @@
+package io.papermc.paper.datakey.map;
+
+import io.papermc.paper.datakey.DataComponentType;
@ -202,7 +202,7 @@ index 0000000000000000000000000000000000000000..adc0fc866fe04063c1f4a6c0bb98e416
+ return DataComponentPatchMapBridge.Holder.bridge().of(DataComponentPatchMapBridge.Holder.bridge().empty());
+ }
+
+ static PatchedDataComponentMap of(DataComponentMap map) {
+ static PatchedDataComponentMap of(final DataComponentMap map) {
+ return DataComponentPatchMapBridge.Holder.bridge().of(map);
+ }
+
@ -239,8 +239,7 @@ index 0000000000000000000000000000000000000000..adc0fc866fe04063c1f4a6c0bb98e416
+ */
+ void reset(@NotNull DataComponentType type);
+
+ @NotNull
+ DataKeyMapPatch asPatch();
+ @NotNull DataKeyMapPatch asPatch();
+
+ void applyPatch(@NotNull DataKeyMapPatch patch);
+
@ -248,10 +247,10 @@ index 0000000000000000000000000000000000000000..adc0fc866fe04063c1f4a6c0bb98e416
+}
diff --git a/src/main/java/io/papermc/paper/datakey/map/PatchedDataComponentMapHolder.java b/src/main/java/io/papermc/paper/datakey/map/PatchedDataComponentMapHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..57c8452de74e33cdd0f234c08b3b769a1c0c70a4
index 0000000000000000000000000000000000000000..f55d7aaa2e419f3044abdc00f94302c269464a46
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/map/PatchedDataComponentMapHolder.java
@@ -0,0 +1,30 @@
@@ -0,0 +1,34 @@
+package io.papermc.paper.datakey.map;
+
+import io.papermc.paper.datakey.DataComponentType;
@ -265,20 +264,24 @@ index 0000000000000000000000000000000000000000..57c8452de74e33cdd0f234c08b3b769a
+
+ @NotNull PatchedDataComponentMap components();
+
+ default <T> T getData(final DataComponentType.@NotNull Valued<T> dataKey) {
+ return this.components().get(dataKey);
+ default boolean hasData(final DataComponentType type) {
+ return this.components().has(type);
+ }
+
+ default <T> void setData(final DataComponentType.@NotNull Valued<T> dataKey, final @Nullable T value) {
+ this.components().set(dataKey, value);
+ default <T> T getData(final DataComponentType.@NotNull Valued<T> type) {
+ return this.components().get(type);
+ }
+
+ default void setData(final DataComponentType.@NotNull NonValued dataKey) {
+ this.components().set(dataKey);
+ default <T> void setData(final DataComponentType.@NotNull Valued<T> type, final @Nullable T value) {
+ this.components().set(type, value);
+ }
+
+ default <T> void removeData(final @NotNull DataComponentType dataComponentType) {
+ this.components().unset(dataComponentType);
+ default void setData(final DataComponentType.@NotNull NonValued type) {
+ this.components().set(type);
+ }
+
+ default <T> void removeData(final @NotNull DataComponentType type) {
+ this.components().unset(type);
+ }
+
+}
@ -340,7 +343,7 @@ index 0000000000000000000000000000000000000000..60a49ecb5788de79d3a130fd0ddd7c4c
+}
diff --git a/src/main/java/io/papermc/paper/datakey/types/ItemLore.java b/src/main/java/io/papermc/paper/datakey/types/ItemLore.java
new file mode 100644
index 0000000000000000000000000000000000000000..a395f5f3fbd9ffe4cb7fdfa4d60ace937b23bbb4
index 0000000000000000000000000000000000000000..df2611450611c4bb1c6b8b15b526f7b59bc22487
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/types/ItemLore.java
@@ -0,0 +1,40 @@
@ -363,8 +366,8 @@ index 0000000000000000000000000000000000000000..a395f5f3fbd9ffe4cb7fdfa4d60ace93
+ }
+
+ @Contract(value = "_ -> new", pure = true)
+ static ItemLore lore(final List<? extends ComponentLike> lore) {
+ return lore().lore(lore).build();
+ static ItemLore lore(final List<? extends ComponentLike> lines) {
+ return lore().lines(lines).build();
+ }
+
+ @Contract(pure = true)
@ -377,7 +380,7 @@ index 0000000000000000000000000000000000000000..a395f5f3fbd9ffe4cb7fdfa4d60ace93
+ interface Builder {
+
+ @Contract(value = "_ -> this", mutates = "this")
+ Builder lore(List<? extends ComponentLike> lore);
+ Builder lines(List<? extends ComponentLike> lines);
+
+ @Contract(pure = true, value = "-> new")
+ @NotNull ItemLore build();
@ -459,7 +462,7 @@ index 98a970a6582dca22e719a31559c7becea4725cb2..84708afee2316108babbd64c9c667146
/**
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
index 84a7bf0936d35bf42b5ed038d295d5c31740f472..c0c6f7dace959b5726fd7000024725c5e7229ccc 100644
index 84a7bf0936d35bf42b5ed038d295d5c31740f472..6ff3c5150d04b15552286a5f86a54efca4c2fcb6 100644
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
@@ -1,7 +1,6 @@
@ -496,7 +499,7 @@ index 84a7bf0936d35bf42b5ed038d295d5c31740f472..c0c6f7dace959b5726fd7000024725c5
@Deprecated // Paper
public void setType(@NotNull Material type) {
Preconditions.checkArgument(type != null, "Material cannot be null");
+ this.dataKeyMap = io.papermc.paper.datakey.map.DataComponentPatchMapBridge.Holder.bridge().fromItemMeta(type, Bukkit.getItemFactory().asMetaFor(this.getItemMeta(), type)); // Paper - update type first too, we need the old context to resolve the meta from the type
+ this.dataKeyMap = io.papermc.paper.datakey.map.DataComponentPatchMapBridge.Holder.bridge().fromItemAndMeta(type, Bukkit.getItemFactory().asMetaFor(this.getItemMeta(), type)); // Paper - update type first too, we need the old context to resolve the meta from the type
this.type = type;
- if (this.meta != null) {
- this.meta = Bukkit.getItemFactory().asMetaFor(meta, type);
@ -637,7 +640,7 @@ index 84a7bf0936d35bf42b5ed038d295d5c31740f472..c0c6f7dace959b5726fd7000024725c5
- if (this.meta == itemMeta) {
- this.meta = itemMeta.clone();
- }
+ this.dataKeyMap = io.papermc.paper.datakey.map.DataComponentPatchMapBridge.Holder.bridge().fromItemMeta(material, itemMeta);
+ this.dataKeyMap = io.papermc.paper.datakey.map.DataComponentPatchMapBridge.Holder.bridge().fromItemAndMeta(material, itemMeta);
return true;
}

View File

@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..264a8a14d2a778ef4eaa5937342b5978
+}
diff --git a/src/main/java/io/papermc/paper/datakey/ComponentAdapters.java b/src/main/java/io/papermc/paper/datakey/ComponentAdapters.java
new file mode 100644
index 0000000000000000000000000000000000000000..269b49fd9eceed44a0c8fc0baf10b8bfe4e9ead7
index 0000000000000000000000000000000000000000..2b7ebce80662774f751d930c0e7df1f446d2dc8d
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/ComponentAdapters.java
@@ -0,0 +1,71 @@
@ -64,7 +64,7 @@ index 0000000000000000000000000000000000000000..269b49fd9eceed44a0c8fc0baf10b8bf
+public final class ComponentAdapters {
+
+ private static final Function<Unit, Void> UNIT_TO_API_CONVERTER = $ -> {
+ throw new UnsupportedOperationException("Cannot convert the UNIT type to an api value");
+ throw new UnsupportedOperationException("Cannot convert the Unit type to an API value");
+ };
+
+ static final Map<ResourceKey<DataComponentType<?>>, ComponentAdapter<?, ?>> ADAPTERS = new HashMap<>();
@ -114,10 +114,10 @@ index 0000000000000000000000000000000000000000..269b49fd9eceed44a0c8fc0baf10b8bf
+}
diff --git a/src/main/java/io/papermc/paper/datakey/DataComponentPatchBridgeImpl.java b/src/main/java/io/papermc/paper/datakey/DataComponentPatchBridgeImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..12804b65e4c3732cf2347fbb18c99896265331f4
index 0000000000000000000000000000000000000000..af78395dc718a3947ae1001daa48f68fddd135a6
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/DataComponentPatchBridgeImpl.java
@@ -0,0 +1,58 @@
@@ -0,0 +1,57 @@
+package io.papermc.paper.datakey;
+
+import com.mojang.authlib.GameProfile;
@ -134,8 +134,8 @@ index 0000000000000000000000000000000000000000..12804b65e4c3732cf2347fbb18c99896
+
+public class DataComponentPatchBridgeImpl implements io.papermc.paper.datakey.map.DataComponentPatchMapBridge {
+ @Override
+ public PatchedDataComponentMap of(final DataComponentMap keyMap) {
+ return new PaperPatchedDataComponentMap(new net.minecraft.core.component.PatchedDataComponentMap(((PaperDataComponentMap) keyMap).nmsComponentMap));
+ public PatchedDataComponentMap of(final DataComponentMap map) {
+ return new PaperPatchedDataComponentMap(new net.minecraft.core.component.PatchedDataComponentMap(((PaperDataComponentMap) map).map));
+ }
+
+ @Override
@ -145,35 +145,34 @@ index 0000000000000000000000000000000000000000..12804b65e4c3732cf2347fbb18c99896
+
+ @Override
+ public DataComponentMap fromItem(final Material material) {
+ Item item = CraftItemType.bukkitToMinecraft(material);
+ if (item == null) { // Because people can make non item itemstacks still..
+ return new PaperDataComponentMap(net.minecraft.core.component.DataComponentMap.EMPTY);
+ final Item item = CraftItemType.bukkitToMinecraft(material);
+ if (item == null) {
+ // Because people can make non-item itemstacks still..
+ return this.empty();
+ }
+ return new PaperDataComponentMap(item.components());
+ }
+
+ @Override
+ public PatchedDataComponentMap fromItemMeta(final Material material, final ItemMeta itemMeta) {
+
+ public PatchedDataComponentMap fromItemAndMeta(final Material material, final ItemMeta meta) {
+ final CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator() {
+
+ @Override
+ public void skullCallback(final GameProfile gameProfile) {
+ builder.set(DataComponents.PROFILE, new net.minecraft.world.item.component.ResolvableProfile(gameProfile));
+ this.builder.set(DataComponents.PROFILE, new net.minecraft.world.item.component.ResolvableProfile(gameProfile));
+ }
+ };
+ ((CraftMetaItem) itemMeta).applyToItemPublic(tag);
+ ((CraftMetaItem) meta).applyToItemPublic(tag);
+
+ net.minecraft.core.component.PatchedDataComponentMap patchedMap = new net.minecraft.core.component.PatchedDataComponentMap(CraftItemType.bukkitToMinecraft(material).components());
+ patchedMap.applyPatch(tag.builder.build());
+ return new PaperPatchedDataComponentMap(patchedMap);
+ final net.minecraft.core.component.PatchedDataComponentMap map = new net.minecraft.core.component.PatchedDataComponentMap(CraftItemType.bukkitToMinecraft(material).components());
+ map.applyPatch(tag.builder.build());
+ return new PaperPatchedDataComponentMap(map);
+ }
+
+ @Override
+ public ItemMeta toItemMeta(final Material material, final PatchedDataComponentMap dataKeyMap) {
+ ItemStack itemStack = new ItemStack(CraftItemType.bukkitToMinecraft(material));
+ itemStack.restorePatch(((PaperPatchedDataComponentMap) dataKeyMap).patched().asPatch());
+ return CraftItemStack.getItemMeta(itemStack, material);
+ public ItemMeta toItemMeta(final Material material, final PatchedDataComponentMap map) {
+ final ItemStack stack = new ItemStack(CraftItemType.bukkitToMinecraft(material));
+ stack.restorePatch(((PaperPatchedDataComponentMap) map).patched().asPatch());
+ return CraftItemStack.getItemMeta(stack, material);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datakey/NonValuedDataComponentTypeImpl.java b/src/main/java/io/papermc/paper/datakey/NonValuedDataComponentTypeImpl.java
@ -198,7 +197,7 @@ index 0000000000000000000000000000000000000000..67ce3b2960396c86c1ba2cb568b76a98
+}
diff --git a/src/main/java/io/papermc/paper/datakey/PaperComponentType.java b/src/main/java/io/papermc/paper/datakey/PaperComponentType.java
new file mode 100644
index 0000000000000000000000000000000000000000..332b49c1763342d2f7964fdcbefe5b440e762778
index 0000000000000000000000000000000000000000..c5f6005b57e77061900b6c1b145f33f373834247
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/PaperComponentType.java
@@ -0,0 +1,71 @@
@ -223,12 +222,12 @@ index 0000000000000000000000000000000000000000..332b49c1763342d2f7964fdcbefe5b44
+ ComponentAdapters.bootstrap();
+ }
+
+ public static <T> net.minecraft.core.component.DataComponentType<T> bukkitToMinecraft(final DataComponentType bukkitDamageType) {
+ return CraftRegistry.bukkitToMinecraft(bukkitDamageType);
+ public static <T> net.minecraft.core.component.DataComponentType<T> bukkitToMinecraft(final DataComponentType type) {
+ return CraftRegistry.bukkitToMinecraft(type);
+ }
+
+ public static DataComponentType minecraftToBukkit(final net.minecraft.core.component.DataComponentType<?> minecraftDataComponentType) {
+ return CraftRegistry.minecraftToBukkit(minecraftDataComponentType, Registries.DATA_COMPONENT_TYPE, Registry.DATA_COMPONENT_TYPE);
+ public static DataComponentType minecraftToBukkit(final net.minecraft.core.component.DataComponentType<?> type) {
+ return CraftRegistry.minecraftToBukkit(type, Registries.DATA_COMPONENT_TYPE, Registry.DATA_COMPONENT_TYPE);
+ }
+
+ private final NamespacedKey key;
@ -261,24 +260,24 @@ index 0000000000000000000000000000000000000000..332b49c1763342d2f7964fdcbefe5b44
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <NMS> DataComponentType of(final NamespacedKey key, final net.minecraft.core.component.DataComponentType<NMS> dataComponentType) {
+ public static <NMS> DataComponentType of(final NamespacedKey key, final net.minecraft.core.component.DataComponentType<NMS> type) {
+ final ComponentAdapter<NMS, ?> adapter = (ComponentAdapter<NMS, ?>) ComponentAdapters.ADAPTERS.get(ResourceKey.create(Registries.DATA_COMPONENT_TYPE, CraftNamespacedKey.toMinecraft(key)));
+ if (adapter == null) {
+ throw new IllegalArgumentException("No adapter found for " + key);
+ }
+ if (adapter.isValued()) {
+ return new ValuedDataComponentTypeImpl<>(key, dataComponentType, adapter);
+ return new ValuedDataComponentTypeImpl<>(key, type, adapter);
+ } else {
+ return new NonValuedDataComponentTypeImpl<>(key, dataComponentType, adapter);
+ return new NonValuedDataComponentTypeImpl<>(key, type, adapter);
+ }
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datakey/PaperDataComponentMap.java b/src/main/java/io/papermc/paper/datakey/PaperDataComponentMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f03c45dd8855486e7efc1c21c5d43979ca02b87
index 0000000000000000000000000000000000000000..9480d70d41bd53f8d91b72da8506d2862fb771fd
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/PaperDataComponentMap.java
@@ -0,0 +1,45 @@
@@ -0,0 +1,46 @@
+package io.papermc.paper.datakey;
+
+import io.papermc.paper.datakey.map.DataComponentMap;
@ -291,10 +290,10 @@ index 0000000000000000000000000000000000000000..4f03c45dd8855486e7efc1c21c5d4397
+@DefaultQualifier(NonNull.class)
+public class PaperDataComponentMap implements DataComponentMap {
+
+ protected final net.minecraft.core.component.DataComponentMap nmsComponentMap;
+ protected final net.minecraft.core.component.DataComponentMap map;
+
+ public PaperDataComponentMap(final net.minecraft.core.component.DataComponentMap patchedDataComponentMap) {
+ this.nmsComponentMap = patchedDataComponentMap;
+ public PaperDataComponentMap(final net.minecraft.core.component.DataComponentMap map) {
+ this.map = map;
+ }
+
+ @Override
@ -302,14 +301,14 @@ index 0000000000000000000000000000000000000000..4f03c45dd8855486e7efc1c21c5d4397
+ @SuppressWarnings("unchecked")
+ final PaperComponentType<T, Object> typeAsImpl = (PaperComponentType<T, Object>) type;
+ final ComponentAdapter<Object, T> adapter = typeAsImpl.getAdapter();
+ final @Nullable Object value = this.nmsComponentMap.get(typeAsImpl.getHandle());
+ final @Nullable Object value = this.map.get(typeAsImpl.getHandle());
+
+ return value == null ? null : adapter.fromVanilla(value);
+ }
+
+ @Override
+ public Set<DataComponentType> keySet() {
+ final Set<net.minecraft.core.component.DataComponentType<?>> nmsKeys = this.nmsComponentMap.keySet();
+ final Set<net.minecraft.core.component.DataComponentType<?>> nmsKeys = this.map.keySet();
+ final Set<DataComponentType> keys = new HashSet<>(nmsKeys.size());
+ for (final net.minecraft.core.component.DataComponentType<?> nmsKey : nmsKeys) {
+ keys.add(PaperComponentType.minecraftToBukkit(nmsKey));
@ -320,13 +319,14 @@ index 0000000000000000000000000000000000000000..4f03c45dd8855486e7efc1c21c5d4397
+
+ @Override
+ public boolean has(final DataComponentType type) {
+ final PaperComponentType<?, Object> paperComponentType = (PaperComponentType<?, Object>) type;
+ return this.nmsComponentMap.has(paperComponentType.getHandle());
+ @SuppressWarnings("unchecked")
+ final PaperComponentType<?, Object> typeAsImpl = (PaperComponentType<?, Object>) type;
+ return this.map.has(typeAsImpl.getHandle());
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datakey/PaperPatchedDataComponentMap.java b/src/main/java/io/papermc/paper/datakey/PaperPatchedDataComponentMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..1433bc7e982d56788469bceafe6663e4136889d2
index 0000000000000000000000000000000000000000..4fcb07685f4ad84821332dba390f8d4b2246d0f0
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/PaperPatchedDataComponentMap.java
@@ -0,0 +1,71 @@
@ -339,8 +339,8 @@ index 0000000000000000000000000000000000000000..1433bc7e982d56788469bceafe6663e4
+
+public class PaperPatchedDataComponentMap extends PaperDataComponentMap implements PatchedDataComponentMap {
+
+ public PaperPatchedDataComponentMap(final net.minecraft.core.component.PatchedDataComponentMap patchedDataKeyMap) {
+ super(patchedDataKeyMap);
+ public PaperPatchedDataComponentMap(final net.minecraft.core.component.PatchedDataComponentMap map) {
+ super(map);
+ }
+
+ @Override
@ -379,8 +379,8 @@ index 0000000000000000000000000000000000000000..1433bc7e982d56788469bceafe6663e4
+ @SuppressWarnings("unchecked")
+ final PaperComponentType<?, Object> typeAsImpl = (PaperComponentType<?, Object>) type;
+
+ final net.minecraft.core.component.PatchedDataComponentMap patchedDataComponentMap = this.patched();
+ patchedDataComponentMap.applyPatch(patchedDataComponentMap.asPatch().forget((forgetType) -> forgetType == typeAsImpl.getHandle())); // Apply patch with type removed
+ final net.minecraft.core.component.PatchedDataComponentMap map = this.patched();
+ map.applyPatch(map.asPatch().forget((forgetType) -> forgetType == typeAsImpl.getHandle())); // Apply patch with type removed
+ }
+
+ @Override
@ -398,7 +398,7 @@ index 0000000000000000000000000000000000000000..1433bc7e982d56788469bceafe6663e4
+ }
+
+ public net.minecraft.core.component.PatchedDataComponentMap patched() {
+ return ((net.minecraft.core.component.PatchedDataComponentMap) this.nmsComponentMap);
+ return ((net.minecraft.core.component.PatchedDataComponentMap) this.map);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datakey/ValuedDataComponentTypeImpl.java b/src/main/java/io/papermc/paper/datakey/ValuedDataComponentTypeImpl.java
@ -443,10 +443,10 @@ index 0000000000000000000000000000000000000000..38e350b17f0fccb9dbc7353084c70d66
+}
diff --git a/src/main/java/io/papermc/paper/datakey/types/PaperItemLore.java b/src/main/java/io/papermc/paper/datakey/types/PaperItemLore.java
new file mode 100644
index 0000000000000000000000000000000000000000..a98a4e064604b5f589bd220ed5b41c26fb3c00de
index 0000000000000000000000000000000000000000..02db3e26cbbcfe4b564a9699168de4d27005a1a0
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/types/PaperItemLore.java
@@ -0,0 +1,68 @@
@@ -0,0 +1,66 @@
+package io.papermc.paper.datakey.types;
+
+import com.google.common.collect.Lists;
@ -460,26 +460,24 @@ index 0000000000000000000000000000000000000000..a98a4e064604b5f589bd220ed5b41c26
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+import static java.util.Collections.unmodifiableList;
+
+@DefaultQualifier(NonNull.class)
+public record PaperItemLore(
+ net.minecraft.world.item.component.ItemLore itemLore,
+ net.minecraft.world.item.component.ItemLore impl,
+ List<Component> lines,
+ List<Component> styledLines
+) implements ItemLore, Handleable<net.minecraft.world.item.component.ItemLore> {
+
+ public PaperItemLore(final net.minecraft.world.item.component.ItemLore itemLore) {
+ public PaperItemLore(final net.minecraft.world.item.component.ItemLore impl) {
+ this(
+ itemLore,
+ unmodifiableList(Lists.transform(itemLore.lines(), PaperAdventure::asAdventure)),
+ unmodifiableList(Lists.transform(itemLore.styledLines(), PaperAdventure::asAdventure))
+ impl,
+ Collections.unmodifiableList(Lists.transform(impl.lines(), PaperAdventure::asAdventure)),
+ Collections.unmodifiableList(Lists.transform(impl.styledLines(), PaperAdventure::asAdventure))
+ );
+ }
+
+ @Override
+ public net.minecraft.world.item.component.ItemLore getHandle() {
+ return this.itemLore;
+ return this.impl;
+ }
+
+ @Override
@ -497,8 +495,8 @@ index 0000000000000000000000000000000000000000..a98a4e064604b5f589bd220ed5b41c26
+ private List<? extends ComponentLike> lines = Collections.emptyList();
+
+ @Override
+ public ItemLore.Builder lore(final List<? extends ComponentLike> lore) {
+ this.lines = List.copyOf(lore);
+ public ItemLore.Builder lines(final List<? extends ComponentLike> lines) {
+ this.lines = List.copyOf(lines);
+ return this;
+ }
+
@ -511,13 +509,13 @@ index 0000000000000000000000000000000000000000..a98a4e064604b5f589bd220ed5b41c26
+ for (final ComponentLike line : this.lines) {
+ lines.add(PaperAdventure.asVanilla(line.asComponent()));
+ }
+ return new PaperItemLore(new net.minecraft.world.item.component.ItemLore(unmodifiableList(lines)));
+ return new PaperItemLore(new net.minecraft.world.item.component.ItemLore(Collections.unmodifiableList(lines)));
+ }
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datakey/types/PaperUnbreakable.java b/src/main/java/io/papermc/paper/datakey/types/PaperUnbreakable.java
new file mode 100644
index 0000000000000000000000000000000000000000..90cd022e6472d161f14db5f2eae0110fa2617fab
index 0000000000000000000000000000000000000000..8af596088fe4dd7d81f6d4d4ebf4c37121b442cb
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datakey/types/PaperUnbreakable.java
@@ -0,0 +1,40 @@
@ -528,21 +526,21 @@ index 0000000000000000000000000000000000000000..90cd022e6472d161f14db5f2eae0110f
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+@DefaultQualifier(NonNull.class)
+public record PaperUnbreakable(net.minecraft.world.item.component.Unbreakable unbreakable) implements Unbreakable, Handleable<net.minecraft.world.item.component.Unbreakable> {
+public record PaperUnbreakable(net.minecraft.world.item.component.Unbreakable impl) implements Unbreakable, Handleable<net.minecraft.world.item.component.Unbreakable> {
+
+ @Override
+ public boolean showInTooltip() {
+ return this.unbreakable.showInTooltip();
+ return this.impl.showInTooltip();
+ }
+
+ @Override
+ public Unbreakable showInTooltip(final boolean showInTooltip) {
+ return new PaperUnbreakable(this.unbreakable.withTooltip(showInTooltip));
+ return new PaperUnbreakable(this.impl.withTooltip(showInTooltip));
+ }
+
+ @Override
+ public net.minecraft.world.item.component.Unbreakable getHandle() {
+ return this.unbreakable;
+ return this.impl;
+ }
+
+ static final class BuilderImpl implements Unbreakable.Builder {
@ -698,6 +696,104 @@ index 0000000000000000000000000000000000000000..d43e2b2d0e86ed585ba7bfd4e26d6259
@@ -0,0 +1 @@
+io.papermc.paper.datakey.types.ComponentTypesBridgesImpl
\ No newline at end of file
diff --git a/src/test/java/io/papermc/paper/item/ItemStackDataComponentTest.java b/src/test/java/io/papermc/paper/item/ItemStackDataComponentTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..96a336cb1e291782d0d524c794bf370e05e064a0
--- /dev/null
+++ b/src/test/java/io/papermc/paper/item/ItemStackDataComponentTest.java
@@ -0,0 +1,92 @@
+package io.papermc.paper.item;
+
+import io.papermc.paper.datakey.DataComponentType;
+import io.papermc.paper.datakey.DataComponentTypes;
+import io.papermc.paper.datakey.types.Unbreakable;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemFlag;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.Damageable;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.inventory.meta.Repairable;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+class ItemStackDataComponentTest extends AbstractTestingBase {
+
+ @Test
+ void testMaxStackSize() {
+ final ItemStack stack = new ItemStack(Material.STONE);
+ testWithMeta(stack, DataComponentTypes.MAX_STACK_SIZE, 32, ItemMeta.class, ItemMeta::getMaxStackSize, ItemMeta::setMaxStackSize);
+ }
+
+ @Test
+ void testMaxDamage() {
+ final ItemStack stack = new ItemStack(Material.STONE);
+ testWithMeta(stack, DataComponentTypes.MAX_DAMAGE, 120, Damageable.class, Damageable::getMaxDamage, Damageable::setMaxDamage);
+ }
+
+ @Test
+ void testDamage() {
+ final ItemStack stack = new ItemStack(Material.STONE);
+ testWithMeta(stack, DataComponentTypes.DAMAGE, 120, Damageable.class, Damageable::getDamage, Damageable::setDamage);
+ }
+
+ @Test
+ void testUnbreakable() {
+ final ItemStack stack = new ItemStack(Material.STONE);
+ stack.setData(DataComponentTypes.UNBREAKABLE, Unbreakable.unbreakable().showInTooltip(false).build());
+
+ Assertions.assertTrue(stack.getItemMeta().isUnbreakable());
+ Assertions.assertTrue(stack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_UNBREAKABLE));
+ stack.setData(DataComponentTypes.UNBREAKABLE, null);
+ Assertions.assertFalse(stack.getItemMeta().isUnbreakable());
+ }
+
+ @Test
+ void testHideAdditionalTooltip() {
+ final ItemStack stack = new ItemStack(Material.STONE);
+ stack.setData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP);
+
+ Assertions.assertTrue(stack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_ADDITIONAL_TOOLTIP));
+ stack.removeData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP);
+ Assertions.assertFalse(stack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_ADDITIONAL_TOOLTIP));
+ }
+
+ @Test
+ void testHideTooltip() {
+ ItemStack stack = new ItemStack(Material.STONE);
+ stack.setData(DataComponentTypes.HIDE_TOOLTIP);
+
+ Assertions.assertEquals(stack.getItemMeta().isHideTooltip(), stack.hasData(DataComponentTypes.HIDE_TOOLTIP));
+ Assertions.assertTrue(stack.getItemMeta().isHideTooltip());
+ stack.removeData(DataComponentTypes.HIDE_TOOLTIP);
+ Assertions.assertFalse(stack.getItemMeta().isHideTooltip());
+ stack = new ItemStack(Material.STONE);
+
+ stack.removeData(DataComponentTypes.HIDE_TOOLTIP);
+ Assertions.assertFalse(stack.getItemMeta().isHideTooltip());
+ Assertions.assertEquals(stack.getItemMeta().isHideTooltip(), stack.hasData(DataComponentTypes.HIDE_TOOLTIP));
+ }
+
+ @Test
+ void testRepairCost() {
+ final ItemStack stack = new ItemStack(Material.STONE);
+ testWithMeta(stack, DataComponentTypes.REPAIR_COST, 120, Repairable.class, Repairable::getRepairCost, Repairable::setRepairCost);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T, M> void testWithMeta(final ItemStack stack, final DataComponentType.Valued<T> type, final T value, final Class<M> metaType, final Function<M, T> metaGetter, final BiConsumer<M, T> metaSetter) {
+ stack.setData(type, value);
+
+ Assertions.assertEquals(value, stack.getData(type));
+
+ final ItemMeta meta = stack.getItemMeta();
+ final M typedMeta = Assertions.assertInstanceOf(metaType, meta);
+
+ Assertions.assertEquals(metaGetter.apply(typedMeta), value);
+ }
+}
diff --git a/src/test/java/io/papermc/paper/item/MetaComparisonTest.java b/src/test/java/io/papermc/paper/item/MetaComparisonTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..03aeb992c274d762c1b3475458851671d3045ffc
@ -988,103 +1084,6 @@ index 0000000000000000000000000000000000000000..03aeb992c274d762c1b3475458851671
+ }
+
+}
diff --git a/src/test/java/io/papermc/paper/item/MetaDataComponentTypeMetaTest.java b/src/test/java/io/papermc/paper/item/MetaDataComponentTypeMetaTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d17b0c368901323fec48c2d828d5d96caa4e413
--- /dev/null
+++ b/src/test/java/io/papermc/paper/item/MetaDataComponentTypeMetaTest.java
@@ -0,0 +1,91 @@
+package io.papermc.paper.item;
+
+import io.papermc.paper.datakey.DataComponentType;
+import io.papermc.paper.datakey.DataComponentTypes;
+import io.papermc.paper.datakey.types.Unbreakable;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemFlag;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.Damageable;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.inventory.meta.Repairable;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+public class MetaDataComponentTypeMetaTest extends AbstractTestingBase {
+
+ @Test
+ public void testMaxStackSizeIntegrity() {
+ ItemStack itemStack = new ItemStack(Material.STONE);
+ testSimpleValue(itemStack, DataComponentTypes.MAX_STACK_SIZE, 32, ItemMeta::getMaxStackSize, ItemMeta::setMaxStackSize, ItemMeta.class);
+ }
+
+ @Test
+ public void testMaxDamageIntegrity() {
+ ItemStack itemStack = new ItemStack(Material.STONE);
+ testSimpleValue(itemStack, DataComponentTypes.MAX_DAMAGE, 120, Damageable::getMaxDamage, Damageable::setMaxDamage, Damageable.class);
+ }
+
+ @Test
+ public void testDamageIntegrity() {
+ ItemStack itemStack = new ItemStack(Material.STONE);
+ testSimpleValue(itemStack, DataComponentTypes.DAMAGE, 120, Damageable::getDamage, Damageable::setDamage, Damageable.class);
+ }
+
+ @Test
+ public void testRepairCost() {
+ ItemStack itemStack = new ItemStack(Material.STONE);
+ testSimpleValue(itemStack, DataComponentTypes.REPAIR_COST, 120, Repairable::getRepairCost, Repairable::setRepairCost, Repairable.class);
+ }
+
+ @Test
+ public void testUnbreakable() {
+ ItemStack itemStack = new ItemStack(Material.STONE);
+ itemStack.components().set(DataComponentTypes.UNBREAKABLE, Unbreakable.unbreakable().showInTooltip(false).build());
+
+ Assertions.assertTrue(itemStack.getItemMeta().isUnbreakable());
+ Assertions.assertTrue(itemStack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_UNBREAKABLE));
+ itemStack.components().set(DataComponentTypes.UNBREAKABLE, null);
+ Assertions.assertFalse(itemStack.getItemMeta().isUnbreakable());
+ }
+
+ @Test
+ public void testToolTipAdditional() {
+ ItemStack itemStack = new ItemStack(Material.STONE);
+ itemStack.components().set(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP);
+
+ Assertions.assertTrue(itemStack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_ADDITIONAL_TOOLTIP));
+ itemStack.components().unset(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP);
+ Assertions.assertFalse(itemStack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_ADDITIONAL_TOOLTIP));
+ }
+
+ @Test
+ public void testToolTip() {
+ ItemStack itemStack = new ItemStack(Material.STONE);
+ itemStack.components().set(DataComponentTypes.HIDE_TOOLTIP);
+
+ Assertions.assertEquals(itemStack.getItemMeta().isHideTooltip(), itemStack.components().has(DataComponentTypes.HIDE_TOOLTIP));
+ Assertions.assertTrue(itemStack.getItemMeta().isHideTooltip());
+ itemStack.components().unset(DataComponentTypes.HIDE_TOOLTIP);
+ Assertions.assertFalse(itemStack.getItemMeta().isHideTooltip());
+ itemStack = new ItemStack(Material.STONE);
+
+ itemStack.components().unset(DataComponentTypes.HIDE_TOOLTIP);
+ Assertions.assertFalse(itemStack.getItemMeta().isHideTooltip());
+ Assertions.assertEquals(itemStack.getItemMeta().isHideTooltip(), itemStack.components().has(DataComponentTypes.HIDE_TOOLTIP));
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T, M> void testSimpleValue(ItemStack itemStack, DataComponentType.Valued<T> dataKey, T value, Function<M, T> metaGetter, BiConsumer<M, T> metaSetter, Class<M> meta) {
+ itemStack.components().set(dataKey, value);
+ Assertions.assertEquals(value, itemStack.components().get(dataKey));
+
+ Assertions.assertEquals(metaGetter.apply((M) itemStack.getItemMeta()), value);
+
+ }
+
+
+}
diff --git a/src/test/java/org/bukkit/PerMaterialTest.java b/src/test/java/org/bukkit/PerMaterialTest.java
index 702a0c29dc2a7fc435fa590c5c66347aea0e014b..419a7dbbe9c50099a4d35c564f7e9c2ba652be75 100644
--- a/src/test/java/org/bukkit/PerMaterialTest.java