aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLulu13022002 <[email protected]>2024-06-27 23:21:07 +0200
committerOwen1212055 <[email protected]>2024-11-18 14:50:38 -0500
commite3e60ca1993e86eb13fa2059c8e4d8012a846441 (patch)
tree76963043c657ecf21af672760d8a515c25169a30
parent92055b6da5d3c59bc17a509fdd3f2f8c2b14a757 (diff)
downloadPaper-e3e60ca1993e86eb13fa2059c8e4d8012a846441.tar.gz
Paper-e3e60ca1993e86eb13fa2059c8e4d8012a846441.zip
some changes
-rw-r--r--patches/api/0480-WIP-DataComponent-API.patch262
-rw-r--r--patches/server/1026-WIP-DataComponent-API.patch221
2 files changed, 297 insertions, 186 deletions
diff --git a/patches/api/0480-WIP-DataComponent-API.patch b/patches/api/0480-WIP-DataComponent-API.patch
index c3f1397a6d..e7927fc859 100644
--- a/patches/api/0480-WIP-DataComponent-API.patch
+++ b/patches/api/0480-WIP-DataComponent-API.patch
@@ -6,21 +6,14 @@ Subject: [PATCH] WIP DataComponent API
diff --git a/src/main/java/io/papermc/paper/block/BlockPredicate.java b/src/main/java/io/papermc/paper/block/BlockPredicate.java
new file mode 100644
-index 0000000000000000000000000000000000000000..abd1985275d59bc2377eb386a7f06c13dfa2ede0
+index 0000000000000000000000000000000000000000..360f2b0075a478a034b1baddd1e7c70d252f84f7
--- /dev/null
+++ b/src/main/java/io/papermc/paper/block/BlockPredicate.java
-@@ -0,0 +1,65 @@
+@@ -0,0 +1,54 @@
+package io.papermc.paper.block;
+
-+import io.papermc.paper.registry.RegistryBuilder;
-+import io.papermc.paper.registry.data.EnchantmentRegistryEntry;
+import io.papermc.paper.registry.set.RegistryKeySet;
-+import org.bukkit.Bukkit;
-+import org.bukkit.Location;
+import org.bukkit.block.BlockType;
-+import org.bukkit.enchantments.Enchantment;
-+import org.bukkit.inventory.ItemType;
-+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
@@ -45,7 +38,7 @@ index 0000000000000000000000000000000000000000..abd1985275d59bc2377eb386a7f06c13
+ private @Nullable RegistryKeySet<BlockType> blocks = null;
+
+ @Override
-+ public @NonNull Builder blocks(@Nullable final RegistryKeySet<@NotNull BlockType> blocks) {
++ public @NotNull Builder blocks(@Nullable final RegistryKeySet<@NotNull BlockType> blocks) {
+ this.blocks = blocks;
+ return this;
+ }
@@ -59,21 +52,17 @@ index 0000000000000000000000000000000000000000..abd1985275d59bc2377eb386a7f06c13
+ return new BuilderImpl();
+ }
+
-+ @Nullable
-+ RegistryKeySet<@org.jetbrains.annotations.NotNull BlockType> blocks();
++ @Nullable RegistryKeySet<@org.jetbrains.annotations.NotNull BlockType> blocks();
+
+ @ApiStatus.Experimental
+ @ApiStatus.NonExtendable
+ interface Builder {
+
+ @Contract(value = "_ -> this", mutates = "this")
-+ @NonNull
-+ Builder blocks(@Nullable RegistryKeySet<@NotNull BlockType> blocks);
++ @NotNull Builder blocks(@Nullable RegistryKeySet<@NotNull BlockType> blocks);
+
-+ @NotNull
-+ BlockPredicate build();
++ @NotNull BlockPredicate build();
+ }
-+
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/ComponentBuilder.java b/src/main/java/io/papermc/paper/datacomponent/ComponentBuilder.java
new file mode 100644
@@ -105,7 +94,7 @@ index 0000000000000000000000000000000000000000..6eb69eb0f220a3a5e63d8315802b4966
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/DataComponentType.java b/src/main/java/io/papermc/paper/datacomponent/DataComponentType.java
new file mode 100644
-index 0000000000000000000000000000000000000000..3152cc9cf29e7fd21b25f4c7a2b3d0b5bbf49d87
+index 0000000000000000000000000000000000000000..e3fe89c9927d3b82ac7f6cadd51db565d8ab8aa5
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/DataComponentType.java
@@ -0,0 +1,27 @@
@@ -119,9 +108,9 @@ index 0000000000000000000000000000000000000000..3152cc9cf29e7fd21b25f4c7a2b3d0b5
+
+ /**
+ * Checks if this data component type is persistent, or
-+ * that it will be saved with any itemstack it's attached to.
++ * that it will be saved with any item stack it's attached to.
+ *
-+ * @return true if persistent, false otherwise
++ * @return {@code true} if persistent, false otherwise
+ */
+ boolean isPersistent();
+
@@ -542,10 +531,10 @@ index 0000000000000000000000000000000000000000..270f98e95b1d0322a42bad52d492fa00
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/BundleContents.java b/src/main/java/io/papermc/paper/datacomponent/item/BundleContents.java
new file mode 100644
-index 0000000000000000000000000000000000000000..e3443702bfad57aa1a66331060f33b2e406ca153
+index 0000000000000000000000000000000000000000..07b3efef6fa502468138c3fef4a9e9d8b1f06b93
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/BundleContents.java
-@@ -0,0 +1,59 @@
+@@ -0,0 +1,62 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -580,6 +569,7 @@ index 0000000000000000000000000000000000000000..e3443702bfad57aa1a66331060f33b2e
+
+ /**
+ * Lists the items that are currently stored inside of this component.
++ *
+ * @return items
+ */
+ @Contract(value = "-> new", pure = true)
@@ -590,6 +580,7 @@ index 0000000000000000000000000000000000000000..e3443702bfad57aa1a66331060f33b2e
+
+ /**
+ * Adds an item to this builder.
++ *
+ * @param stack item
+ * @return self
+ */
@@ -598,6 +589,7 @@ index 0000000000000000000000000000000000000000..e3443702bfad57aa1a66331060f33b2e
+
+ /**
+ * Adds items to this builder.
++ *
+ * @param stacks items
+ * @return self
+ */
@@ -607,10 +599,10 @@ index 0000000000000000000000000000000000000000..e3443702bfad57aa1a66331060f33b2e
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ChargedProjectiles.java b/src/main/java/io/papermc/paper/datacomponent/item/ChargedProjectiles.java
new file mode 100644
-index 0000000000000000000000000000000000000000..505f93dec42585072f518b4484fdee176e941f50
+index 0000000000000000000000000000000000000000..7c703b696cfe966a4dc400c419f97a1c9334b4fb
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/ChargedProjectiles.java
-@@ -0,0 +1,59 @@
+@@ -0,0 +1,62 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -645,7 +637,8 @@ index 0000000000000000000000000000000000000000..505f93dec42585072f518b4484fdee17
+
+ /**
+ * Lists the projectiles that are currently loaded into this component.
-+ * @return
++ *
++ * @return the loaded projectiles
+ */
+ @Contract(value = "-> new", pure = true)
+ @NonNull @Unmodifiable List<@NonNull ItemStack> projectiles();
@@ -655,27 +648,29 @@ index 0000000000000000000000000000000000000000..505f93dec42585072f518b4484fdee17
+
+ /**
+ * Adds a projectile to be loaded in this builder.
-+ * @param itemStack projectile
++ *
++ * @param stack projectile
+ * @return self
+ */
+ @Contract(value = "_ -> this", mutates = "this")
-+ @NonNull Builder add(@NonNull ItemStack itemStack);
++ @NonNull Builder add(@NonNull ItemStack stack);
+
+ /**
+ * Adds projectiles to be loaded in this builder.
-+ * @param itemStacks projectiles
++ *
++ * @param stacks projectiles
+ * @return self
+ */
+ @Contract(value = "_ -> this", mutates = "this")
-+ @NonNull Builder addAll(@NonNull List<@NonNull ItemStack> itemStacks);
++ @NonNull Builder addAll(@NonNull List<@NonNull ItemStack> stacks);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ComponentTypesBridge.java b/src/main/java/io/papermc/paper/datacomponent/item/ComponentTypesBridge.java
new file mode 100644
-index 0000000000000000000000000000000000000000..a1c78fae5327ef9f9398e00a0b20b5171333bba7
+index 0000000000000000000000000000000000000000..1cbb8da68dcc0b2af271d6a4e8782bfa7459b7c6
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/ComponentTypesBridge.java
-@@ -0,0 +1,88 @@
+@@ -0,0 +1,89 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.registry.set.RegistryKeySet;
@@ -684,6 +679,7 @@ index 0000000000000000000000000000000000000000..a1c78fae5327ef9f9398e00a0b20b517
+import java.util.ServiceLoader;
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.util.TriState;
++import org.bukkit.JukeboxSong;
+import org.bukkit.block.BlockType;
+import org.bukkit.inventory.meta.trim.ArmorTrim;
+import org.bukkit.map.MapCursor;
@@ -756,7 +752,7 @@ index 0000000000000000000000000000000000000000..a1c78fae5327ef9f9398e00a0b20b517
+
+ ItemContainerContents.Builder itemContainerContents();
+
-+ JukeboxPlayable.Builder jukeboxPlayable();
++ JukeboxPlayable.Builder jukeboxPlayable(JukeboxSong song);
+
+ Tool.Builder tool();
+
@@ -799,10 +795,10 @@ index 0000000000000000000000000000000000000000..e93f962fc51c0f260719fccad7ccdadc
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/DyedItemColor.java b/src/main/java/io/papermc/paper/datacomponent/item/DyedItemColor.java
new file mode 100644
-index 0000000000000000000000000000000000000000..ee9983f45d4457935381fac9bf44455a59661e6d
+index 0000000000000000000000000000000000000000..3c0061339a534cf7f255fa4ba3b5687721c18616
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/DyedItemColor.java
-@@ -0,0 +1,43 @@
+@@ -0,0 +1,45 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -829,6 +825,7 @@ index 0000000000000000000000000000000000000000..ee9983f45d4457935381fac9bf44455a
+
+ /**
+ * Color of the item.
++ *
+ * @return color
+ */
+ @Contract(value = "-> new", pure = true)
@@ -839,6 +836,7 @@ index 0000000000000000000000000000000000000000..ee9983f45d4457935381fac9bf44455a
+
+ /**
+ * Sets the color of this builder.
++ *
+ * @param color color
+ * @return self
+ */
@@ -848,16 +846,17 @@ index 0000000000000000000000000000000000000000..ee9983f45d4457935381fac9bf44455a
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/Fireworks.java b/src/main/java/io/papermc/paper/datacomponent/item/Fireworks.java
new file mode 100644
-index 0000000000000000000000000000000000000000..6b3bbe5038f4b2527485eec3848fb0b4bcd640a5
+index 0000000000000000000000000000000000000000..feb1addc53213b2d32dc81614a7401e76a5aa38b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/Fireworks.java
-@@ -0,0 +1,68 @@
+@@ -0,0 +1,75 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
+import java.util.List;
+import org.bukkit.FireworkEffect;
+import org.checkerframework.checker.nullness.qual.NonNull;
++import org.checkerframework.common.value.qual.IntRange;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Unmodifiable;
@@ -880,16 +879,19 @@ index 0000000000000000000000000000000000000000..6b3bbe5038f4b2527485eec3848fb0b4
+
+ /**
+ * Lists the effects stored in this component.
-+ * @return
++ *
++ * @return the effects
+ */
+ @Contract(pure = true)
+ @NonNull @Unmodifiable List<@NonNull FireworkEffect> effects();
+
+ /**
+ * Number of gunpowder in this component.
-+ * @return
++ *
++ * @return the flight duration
+ */
+ @Contract(pure = true)
++ @IntRange(from = 0, to = 255)
+ int flightDuration();
+
+ @ApiStatus.NonExtendable
@@ -897,14 +899,16 @@ index 0000000000000000000000000000000000000000..6b3bbe5038f4b2527485eec3848fb0b4
+
+ /**
+ * Sets the number of gunpowder used in this builder.
++ *
+ * @param duration duration
+ * @return self
+ */
+ @Contract(value = "_ -> this", mutates = "this")
-+ @NonNull Builder flightDuration(int duration);
++ @NonNull Builder flightDuration(@IntRange(from = 0, to = 255) int duration);
+
+ /**
+ * Adds an explosion to this builder.
++ *
+ * @param effect effect
+ * @return self
+ */
@@ -913,6 +917,7 @@ index 0000000000000000000000000000000000000000..6b3bbe5038f4b2527485eec3848fb0b4
+
+ /**
+ * Adds explosions to this builder.
++ *
+ * @param effects effects
+ * @return self
+ */
@@ -922,10 +927,10 @@ index 0000000000000000000000000000000000000000..6b3bbe5038f4b2527485eec3848fb0b4
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/FoodProperties.java b/src/main/java/io/papermc/paper/datacomponent/item/FoodProperties.java
new file mode 100644
-index 0000000000000000000000000000000000000000..f431e1d6fbf5c1d9dbd59f513cf2ba4af4e2786f
+index 0000000000000000000000000000000000000000..451d9656707c61bca93193284dbf0f28a5190de8
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/FoodProperties.java
-@@ -0,0 +1,108 @@
+@@ -0,0 +1,114 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -934,9 +939,9 @@ index 0000000000000000000000000000000000000000..f431e1d6fbf5c1d9dbd59f513cf2ba4a
+import org.bukkit.potion.PotionEffect;
+import org.checkerframework.checker.index.qual.NonNegative;
+import org.checkerframework.checker.nullness.qual.NonNull;
++import org.checkerframework.checker.nullness.qual.Nullable;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
-+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
+
@@ -949,6 +954,7 @@ index 0000000000000000000000000000000000000000..f431e1d6fbf5c1d9dbd59f513cf2ba4a
+
+ /**
+ * Number of food points to restore when eaten
++ *
+ * @return non-negative integer
+ */
+ @Contract(pure = true)
@@ -957,31 +963,34 @@ index 0000000000000000000000000000000000000000..f431e1d6fbf5c1d9dbd59f513cf2ba4a
+
+ /**
+ * Amount of saturation to restore when eaten
-+ * @return saturation
++ *
++ * @return the saturation
+ */
+ @Contract(pure = true)
+ float saturation();
+
+ /**
+ * If true, this food can be eaten even if not hungry.
-+ * @return can be eaten
++ *
++ * @return can always be eaten
+ */
+ @Contract(pure = true)
+ boolean canAlwaysEat();
+
+ /**
+ * The number of seconds that it takes to eat this food item.
-+ * @return seconds
++ *
++ * @return the number seconds to eat that food
+ */
+ @Contract(pure = true)
+ float eatSeconds();
+
-+ @Nullable
+ @Contract(pure = true)
-+ ItemStack usingConvertsTo();
++ @Nullable ItemStack usingConvertsTo();
+
+ /**
+ * List of effects to apply when eaten.
++ *
+ * @return effects
+ */
+ @Unmodifiable @NonNull List<@NonNull PossibleEffect> effects();
@@ -998,12 +1007,14 @@ index 0000000000000000000000000000000000000000..f431e1d6fbf5c1d9dbd59f513cf2ba4a
+
+ /**
+ * Effect instance
++ *
+ * @return effect
+ */
+ @NonNull PotionEffect effect();
+
+ /**
+ * Float between 0 and 1, chance for the effect to be applied.
++ *
+ * @return chance
+ */
+ float probability();
@@ -1036,10 +1047,10 @@ index 0000000000000000000000000000000000000000..f431e1d6fbf5c1d9dbd59f513cf2ba4a
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ItemAdventurePredicate.java b/src/main/java/io/papermc/paper/datacomponent/item/ItemAdventurePredicate.java
new file mode 100644
-index 0000000000000000000000000000000000000000..be1042bc02a41b837eeedfe4877dcf2106db05f5
+index 0000000000000000000000000000000000000000..8b71f115c853241091019c612112331706849373
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemAdventurePredicate.java
-@@ -0,0 +1,40 @@
+@@ -0,0 +1,42 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.block.BlockPredicate;
@@ -1063,18 +1074,20 @@ index 0000000000000000000000000000000000000000..be1042bc02a41b837eeedfe4877dcf21
+
+ /**
+ * List of block predicates that control if the action is allowed.
++ *
+ * @return predicates
+ */
+ @Contract(pure = true)
-+ @NonNull @Unmodifiable List<@NonNull BlockPredicate> modifiers();
++ @NonNull @Unmodifiable List<@NonNull BlockPredicate> predicates();
+
+ @ApiStatus.NonExtendable
+ interface Builder extends ShownInTooltip.Builder<Builder>, ComponentBuilder<ItemAdventurePredicate> {
+ /**
+ * Adds a block predicate to this builder.
++ *
+ * @param predicate predicate
+ * @return self
-+ * @see #modifiers()
++ * @see #predicates()
+ */
+ @Contract(value = "_, _ -> this", mutates = "this")
+ @NonNull Builder addPredicate(@NonNull BlockPredicate predicate);
@@ -1082,10 +1095,10 @@ index 0000000000000000000000000000000000000000..be1042bc02a41b837eeedfe4877dcf21
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ItemArmorTrim.java b/src/main/java/io/papermc/paper/datacomponent/item/ItemArmorTrim.java
new file mode 100644
-index 0000000000000000000000000000000000000000..8c806c19cf294a08078c6a5b89107d16528b02f5
+index 0000000000000000000000000000000000000000..dc968b953f89fd3a07eb633370a95879bc369f8c
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemArmorTrim.java
-@@ -0,0 +1,43 @@
+@@ -0,0 +1,45 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -1105,13 +1118,14 @@ index 0000000000000000000000000000000000000000..8c806c19cf294a08078c6a5b89107d16
+ return itemArmorTrim(armorTrim).showInTooltip(showInTooltip).build();
+ }
+
-+ @Contract(value = "_, -> new", pure = true)
++ @Contract(value = "_ -> new", pure = true)
+ static ItemArmorTrim.@NonNull Builder itemArmorTrim(final @NonNull ArmorTrim armorTrim) {
+ return ComponentTypesBridge.bridge().itemArmorTrim(armorTrim);
+ }
+
+ /**
+ * Armor trim present on this item.
++ *
+ * @return trim
+ */
+ @Contract(pure = true)
@@ -1122,6 +1136,7 @@ index 0000000000000000000000000000000000000000..8c806c19cf294a08078c6a5b89107d16
+
+ /**
+ * Sets the item trim for this builder.
++ *
+ * @param armorTrim trim
+ * @return self
+ */
@@ -1131,10 +1146,10 @@ index 0000000000000000000000000000000000000000..8c806c19cf294a08078c6a5b89107d16
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ItemAttributeModifiers.java b/src/main/java/io/papermc/paper/datacomponent/item/ItemAttributeModifiers.java
new file mode 100644
-index 0000000000000000000000000000000000000000..2fdb6e02235ea28c63bb0b3b6edeecef98a1b996
+index 0000000000000000000000000000000000000000..32432542a4c11f0f5c5c7e397ac9a3c51530376b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemAttributeModifiers.java
-@@ -0,0 +1,55 @@
+@@ -0,0 +1,57 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -1159,6 +1174,7 @@ index 0000000000000000000000000000000000000000..2fdb6e02235ea28c63bb0b3b6edeecef
+
+ /**
+ * Lists the attribute modifiers that are present on this item.
++ *
+ * @return modifiers
+ */
+ @Contract(pure = true)
@@ -1182,6 +1198,7 @@ index 0000000000000000000000000000000000000000..2fdb6e02235ea28c63bb0b3b6edeecef
+
+ /**
+ * Adds a modifier to this builder.
++ *
+ * @param attribute attribute
+ * @param attributeModifier modifier
+ * @return self
@@ -1240,10 +1257,10 @@ index 0000000000000000000000000000000000000000..a748ef9a97a3aa1bba794470cc7c2a8c
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ItemEnchantments.java b/src/main/java/io/papermc/paper/datacomponent/item/ItemEnchantments.java
new file mode 100644
-index 0000000000000000000000000000000000000000..1ac01e0937c33c2588af383ec18f50190c852060
+index 0000000000000000000000000000000000000000..a6420ba58822faa3cf6be130d1afc865000918dc
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemEnchantments.java
-@@ -0,0 +1,55 @@
+@@ -0,0 +1,58 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -1262,7 +1279,7 @@ index 0000000000000000000000000000000000000000..1ac01e0937c33c2588af383ec18f5019
+public interface ItemEnchantments extends ShownInTooltip<ItemEnchantments> {
+
+ @Contract(value = "_, _ -> new", pure = true)
-+ static @NonNull ItemEnchantments itemEnchantments(final @NonNull Map<Enchantment, @IntRange(from = 0, to = 255) Integer> enchantments, final boolean showInTooltip) {
++ static @NonNull ItemEnchantments itemEnchantments(final @NonNull Map<Enchantment, @IntRange(from = 1, to = 255) Integer> enchantments, final boolean showInTooltip) {
+ return itemEnchantments().addAll(enchantments).showInTooltip(showInTooltip).build();
+ }
+
@@ -1273,38 +1290,41 @@ index 0000000000000000000000000000000000000000..1ac01e0937c33c2588af383ec18f5019
+
+ /**
+ * Enchantments currently present on this item.
++ *
+ * @return enchantments
+ */
+ @Contract(pure = true)
-+ @NonNull @Unmodifiable Map<@NonNull Enchantment, @NonNull @IntRange(from = 0, to = 255) Integer> enchantments();
++ @NonNull @Unmodifiable Map<@NonNull Enchantment, @NonNull @IntRange(from = 1, to = 255) Integer> enchantments();
+
+ @ApiStatus.NonExtendable
+ interface Builder extends ShownInTooltip.Builder<Builder>, ComponentBuilder<ItemEnchantments> {
+
+ /**
+ * Adds an enchantment with the given level to this component.
++ *
+ * @param enchantment enchantment
+ * @param level level
+ * @return self
+ */
+ @Contract(value = "_, _ -> this", mutates = "this")
-+ @NonNull Builder add(@NonNull Enchantment enchantment, int level);
++ @NonNull Builder add(@NonNull Enchantment enchantment, @IntRange(from = 1, to = 255) int level);
+
+ /**
+ * Adds enchantments with the given level to this component.
++ *
+ * @param enchantments enchantments
+ * @return self
+ */
+ @Contract(value = "_ -> this", mutates = "this")
-+ @NonNull Builder addAll(@NonNull Map<@NonNull Enchantment, @NonNull @IntRange(from = 0, to = 255) Integer> enchantments);
++ @NonNull Builder addAll(@NonNull Map<@NonNull Enchantment, @NonNull @IntRange(from = 1, to = 255) Integer> enchantments);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ItemLore.java b/src/main/java/io/papermc/paper/datacomponent/item/ItemLore.java
new file mode 100644
-index 0000000000000000000000000000000000000000..655ca9fedbf4e5c12ec2016c5779e47431a459e1
+index 0000000000000000000000000000000000000000..dafb334c6b4ab41398e1473d39e1047a8ca362b2
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemLore.java
-@@ -0,0 +1,69 @@
+@@ -0,0 +1,74 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -1334,6 +1354,7 @@ index 0000000000000000000000000000000000000000..655ca9fedbf4e5c12ec2016c5779e474
+
+ /**
+ * Lists the components that are added to an item's tooltip.
++ *
+ * @return component list
+ */
+ @Contract(pure = true)
@@ -1341,6 +1362,7 @@ index 0000000000000000000000000000000000000000..655ca9fedbf4e5c12ec2016c5779e474
+
+ /**
+ * Lists the styled components (example: italicized and purple) that are added to an item's tooltip.
++ *
+ * @return component list
+ */
+ @Contract(pure = true)
@@ -1351,6 +1373,7 @@ index 0000000000000000000000000000000000000000..655ca9fedbf4e5c12ec2016c5779e474
+
+ /**
+ * Sets the components of this lore.
++ *
+ * @param lines components
+ * @return self
+ */
@@ -1359,6 +1382,7 @@ index 0000000000000000000000000000000000000000..655ca9fedbf4e5c12ec2016c5779e474
+
+ /**
+ * Adds a component to the lore.
++ *
+ * @param line component
+ * @return self
+ */
@@ -1367,6 +1391,7 @@ index 0000000000000000000000000000000000000000..655ca9fedbf4e5c12ec2016c5779e474
+
+ /**
+ * Adds components to the lore.
++ *
+ * @param lines components
+ * @return self
+ */
@@ -1376,7 +1401,7 @@ index 0000000000000000000000000000000000000000..655ca9fedbf4e5c12ec2016c5779e474
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/JukeboxPlayable.java b/src/main/java/io/papermc/paper/datacomponent/item/JukeboxPlayable.java
new file mode 100644
-index 0000000000000000000000000000000000000000..27121491d961fac5f2492ba2fb786682164e9791
+index 0000000000000000000000000000000000000000..ece9afbceb21dec772111a1e7a6813d6a7d39656
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/JukeboxPlayable.java
@@ -0,0 +1,26 @@
@@ -1390,9 +1415,9 @@ index 0000000000000000000000000000000000000000..27121491d961fac5f2492ba2fb786682
+
+public interface JukeboxPlayable extends ShownInTooltip<JukeboxPlayable> {
+
-+ @Contract(value = "-> new", pure = true)
-+ static JukeboxPlayable.@NonNull Builder jukeboxPlayable() {
-+ return ComponentTypesBridge.bridge().jukeboxPlayable();
++ @Contract(value = "_ -> new", pure = true)
++ static JukeboxPlayable.@NonNull Builder jukeboxPlayable(@NonNull JukeboxSong song) {
++ return ComponentTypesBridge.bridge().jukeboxPlayable(song);
+ }
+
+ @Contract(pure = true)
@@ -1401,7 +1426,7 @@ index 0000000000000000000000000000000000000000..27121491d961fac5f2492ba2fb786682
+ @ApiStatus.NonExtendable
+ interface Builder extends ShownInTooltip.Builder<JukeboxPlayable.Builder>, ComponentBuilder<JukeboxPlayable> {
+
-+ @Contract(value = "_, -> this", mutates = "this")
++ @Contract(value = "_ -> this", mutates = "this")
+ @NonNull
+ Builder jukeboxSong(@NonNull JukeboxSong song);
+ }
@@ -1441,10 +1466,10 @@ index 0000000000000000000000000000000000000000..cf6a2e8e6640deeae05283b3cb5755a4
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/LodestoneTracker.java b/src/main/java/io/papermc/paper/datacomponent/item/LodestoneTracker.java
new file mode 100644
-index 0000000000000000000000000000000000000000..3b99f6b9cfeba3fdb37aaea92c7f6de19c222373
+index 0000000000000000000000000000000000000000..e5c6feb0267b05aab99d90e351ae2e848711a79b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/LodestoneTracker.java
-@@ -0,0 +1,59 @@
+@@ -0,0 +1,63 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -1472,6 +1497,7 @@ index 0000000000000000000000000000000000000000..3b99f6b9cfeba3fdb37aaea92c7f6de1
+
+ /**
+ * The location that the compass should point towards.
++ *
+ * @return location
+ */
+ @Contract(value = "-> new", pure = true)
@@ -1479,6 +1505,7 @@ index 0000000000000000000000000000000000000000..3b99f6b9cfeba3fdb37aaea92c7f6de1
+
+ /**
+ * If true, when the Lodestone at the target position is removed, the component will be removed.
++ *
+ * @return tracked
+ */
+ @Contract(pure = true)
@@ -1489,6 +1516,7 @@ index 0000000000000000000000000000000000000000..3b99f6b9cfeba3fdb37aaea92c7f6de1
+
+ /**
+ * Sets the location to point towards for this builder.
++ *
+ * @param location location to point towards
+ * @return self
+ */
@@ -1497,6 +1525,7 @@ index 0000000000000000000000000000000000000000..3b99f6b9cfeba3fdb37aaea92c7f6de1
+
+ /**
+ * Sets if this location lodestone is tracked for this builder.
++ *
+ * @param tracked is tracked
+ * @return self
+ */
@@ -1506,10 +1535,10 @@ index 0000000000000000000000000000000000000000..3b99f6b9cfeba3fdb37aaea92c7f6de1
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/MapDecorations.java b/src/main/java/io/papermc/paper/datacomponent/item/MapDecorations.java
new file mode 100644
-index 0000000000000000000000000000000000000000..da18b602778bf4c6fc536988d89f77d4585da454
+index 0000000000000000000000000000000000000000..83b6d7b8675fc924c6129d4090ee863a7dc64e3f
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/MapDecorations.java
-@@ -0,0 +1,98 @@
+@@ -0,0 +1,105 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -1538,8 +1567,9 @@ index 0000000000000000000000000000000000000000..da18b602778bf4c6fc536988d89f77d4
+
+ /**
+ * Gets the decoration entry with the given id.
++ *
+ * @param id id
-+ * @return decoration entry, or null if not present
++ * @return decoration entry, or {@code null} if not present
+ */
+ @Contract(pure = true)
+ @Nullable DecorationEntry getDecoration(@NonNull String id);
@@ -1560,6 +1590,7 @@ index 0000000000000000000000000000000000000000..da18b602778bf4c6fc536988d89f77d4
+
+ /**
+ * Type of decoration.
++ *
+ * @return type
+ */
+ @Contract(pure = true)
@@ -1567,6 +1598,7 @@ index 0000000000000000000000000000000000000000..da18b602778bf4c6fc536988d89f77d4
+
+ /**
+ * X world coordinate of the decoration.
++ *
+ * @return x
+ */
+ @Contract(pure = true)
@@ -1574,13 +1606,15 @@ index 0000000000000000000000000000000000000000..da18b602778bf4c6fc536988d89f77d4
+
+ /**
+ * Z world coordinate of the decoration.
++ *
+ * @return z
+ */
+ @Contract(pure = true)
+ double z();
+
+ /**
-+ * Clockwise rotation from north in degrees
++ * Clockwise rotation from north in degrees.
++ *
+ * @return rotation
+ */
+ @Contract(pure = true)
@@ -1592,6 +1626,7 @@ index 0000000000000000000000000000000000000000..da18b602778bf4c6fc536988d89f77d4
+
+ /**
+ * Puts the decoration with the given id in this builder.
++ *
+ * @param id id
+ * @param entry decoration
+ * @return self
@@ -1601,6 +1636,7 @@ index 0000000000000000000000000000000000000000..da18b602778bf4c6fc536988d89f77d4
+
+ /**
+ * Puts all the decoration with the given id in this builder.
++ *
+ * @param entries decorations
+ * @return self
+ */
@@ -1610,10 +1646,10 @@ index 0000000000000000000000000000000000000000..da18b602778bf4c6fc536988d89f77d4
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/MapID.java b/src/main/java/io/papermc/paper/datacomponent/item/MapID.java
new file mode 100644
-index 0000000000000000000000000000000000000000..17cf58c3577a9d352686b4fcb08e7da629b8af94
+index 0000000000000000000000000000000000000000..74d70614f00391136ff797f900024d13bc9d34b9
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/MapID.java
-@@ -0,0 +1,39 @@
+@@ -0,0 +1,41 @@
+package io.papermc.paper.datacomponent.item;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
@@ -1633,6 +1669,7 @@ index 0000000000000000000000000000000000000000..17cf58c3577a9d352686b4fcb08e7da6
+
+ /**
+ * The map id.
++ *
+ * @return id
+ */
+ @Contract(pure = true)
@@ -1643,6 +1680,7 @@ index 0000000000000000000000000000000000000000..17cf58c3577a9d352686b4fcb08e7da6
+
+ /**
+ * Sets the map id of this builder
++ *
+ * @param id id
+ * @return self
+ */
@@ -1655,10 +1693,10 @@ index 0000000000000000000000000000000000000000..17cf58c3577a9d352686b4fcb08e7da6
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/MapItemColor.java b/src/main/java/io/papermc/paper/datacomponent/item/MapItemColor.java
new file mode 100644
-index 0000000000000000000000000000000000000000..0f4186034ecb6ad1effa681870d24005f0ebe677
+index 0000000000000000000000000000000000000000..38d09482166323e8d06b82977e8bb7a95486afaf
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/MapItemColor.java
-@@ -0,0 +1,39 @@
+@@ -0,0 +1,41 @@
+package io.papermc.paper.datacomponent.item;
+
+import org.bukkit.Color;
@@ -1679,6 +1717,7 @@ index 0000000000000000000000000000000000000000..0f4186034ecb6ad1effa681870d24005
+
+ /**
+ * The tint to apply.
++ *
+ * @return color
+ */
+ @NonNull Color mapColor();
@@ -1688,6 +1727,7 @@ index 0000000000000000000000000000000000000000..0f4186034ecb6ad1effa681870d24005
+
+ /**
+ * Sets the map color of this builder.
++ *
+ * @param color color
+ * @return self
+ */
@@ -1768,10 +1808,10 @@ index 0000000000000000000000000000000000000000..abd94c0c900f7c2bf936e0c5c28ec928
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PotionContents.java b/src/main/java/io/papermc/paper/datacomponent/item/PotionContents.java
new file mode 100644
-index 0000000000000000000000000000000000000000..321f317248834713361985fad47180fc045d1c82
+index 0000000000000000000000000000000000000000..e6779fb88cbb8d7166eecd161aab8620d05485f7
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PotionContents.java
-@@ -0,0 +1,85 @@
+@@ -0,0 +1,92 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -1798,20 +1838,23 @@ index 0000000000000000000000000000000000000000..321f317248834713361985fad47180fc
+
+ /**
+ * The potion type in this item: the item will inherit all effects from this.
-+ * @return potion type, or null if not present
++ *
++ * @return potion type, or {@code null} if not present
+ */
+ @Contract(pure = true)
+ @Nullable PotionType potion();
+
+ /**
+ * Overrides the visual color of the potion
-+ * @return color override, or null if not present
++ *
++ * @return color override, or {@code null} if not present
+ */
+ @Contract(pure = true)
+ @Nullable Color customColor();
+
+ /**
+ * Additional list of effect instances that this item should apply.
++ *
+ * @return effects
+ */
+ @Contract(pure = true)
@@ -1822,6 +1865,7 @@ index 0000000000000000000000000000000000000000..321f317248834713361985fad47180fc
+
+ /**
+ * Sets the potion type for this builder
++ *
+ * @param potionType builder
+ * @see #potion()
+ * @return self
@@ -1831,6 +1875,7 @@ index 0000000000000000000000000000000000000000..321f317248834713361985fad47180fc
+
+ /**
+ * Sets the color override for this builder.
++ *
+ * @param color color
+ * @see #customColor()
+ * @return self
@@ -1840,6 +1885,7 @@ index 0000000000000000000000000000000000000000..321f317248834713361985fad47180fc
+
+ /**
+ * Adds a custom effect instance to this builder.
++ *
+ * @param potionEffect effect
+ * @see #customEffects()
+ * @return self
@@ -1849,6 +1895,7 @@ index 0000000000000000000000000000000000000000..321f317248834713361985fad47180fc
+
+ /**
+ * Adds custom effect instances to this builder.
++ *
+ * @param potionEffects effects
+ * @see #customEffects()
+ * @return self
@@ -1916,7 +1963,7 @@ index 0000000000000000000000000000000000000000..10cb1af6c976659f80839ce46cdddcc8
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/SeededContainerLoot.java b/src/main/java/io/papermc/paper/datacomponent/item/SeededContainerLoot.java
new file mode 100644
-index 0000000000000000000000000000000000000000..c857d9127aa0030b7f4f620242cbd9ba54dae015
+index 0000000000000000000000000000000000000000..d3794500fcbfbcd850aa591d71504002cc096a47
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/SeededContainerLoot.java
@@ -0,0 +1,37 @@
@@ -1936,7 +1983,7 @@ index 0000000000000000000000000000000000000000..c857d9127aa0030b7f4f620242cbd9ba
+ return SeededContainerLoot.seededContainerLoot(lootTableKey).seed(seed).build();
+ }
+
-+ @Contract(value = "_, -> new", pure = true)
++ @Contract(value = "_ -> new", pure = true)
+ static SeededContainerLoot.@NonNull Builder seededContainerLoot(final @NonNull Key lootTableKey) {
+ return ComponentTypesBridge.bridge().seededContainerLoot(lootTableKey);
+ }
@@ -1986,10 +2033,10 @@ index 0000000000000000000000000000000000000000..1e39fc6779e324030fb2890a4568376f
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/SuspiciousStewEffects.java b/src/main/java/io/papermc/paper/datacomponent/item/SuspiciousStewEffects.java
new file mode 100644
-index 0000000000000000000000000000000000000000..b3055cd0b4446b5100ac85312a1cfbce4c8e6714
+index 0000000000000000000000000000000000000000..0b82b863fd130d41a95ed758cdd50364a0bff8f2
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/SuspiciousStewEffects.java
-@@ -0,0 +1,59 @@
+@@ -0,0 +1,62 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -2024,6 +2071,7 @@ index 0000000000000000000000000000000000000000..b3055cd0b4446b5100ac85312a1cfbce
+
+ /**
+ * Effects that will be applied when consuming Suspicious Stew.
++ *
+ * @return effects
+ */
+ @Contract(pure = true)
@@ -2034,6 +2082,7 @@ index 0000000000000000000000000000000000000000..b3055cd0b4446b5100ac85312a1cfbce
+
+ /**
+ * Adds an effect applied to this builder.
++ *
+ * @param entry effect
+ * @return self
+ */
@@ -2042,6 +2091,7 @@ index 0000000000000000000000000000000000000000..b3055cd0b4446b5100ac85312a1cfbce
+
+ /**
+ * Adds effects applied to this builder.
++ *
+ * @param entries effect
+ * @return self
+ */
@@ -2051,12 +2101,13 @@ index 0000000000000000000000000000000000000000..b3055cd0b4446b5100ac85312a1cfbce
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/Tool.java b/src/main/java/io/papermc/paper/datacomponent/item/Tool.java
new file mode 100644
-index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e895c68fce
+index 0000000000000000000000000000000000000000..3195077207827439a57e007ee5719fc88c92ed86
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/Tool.java
-@@ -0,0 +1,122 @@
+@@ -0,0 +1,133 @@
+package io.papermc.paper.datacomponent.item;
+
++import com.google.common.base.Preconditions;
+import io.papermc.paper.datacomponent.ComponentBuilder;
+import java.util.List;
+import io.papermc.paper.registry.set.RegistryKeySet;
@@ -2082,6 +2133,7 @@ index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e8
+
+ /**
+ * Mining speed to use if no rules match and don't override mining speed
++ *
+ * @return default mining speed
+ */
+ @Contract(pure = true)
@@ -2089,6 +2141,7 @@ index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e8
+
+ /**
+ * Amount of durability to remove each time a block is mined with this tool
++ *
+ * @return durability
+ */
+ @Contract(pure = true)
@@ -2096,6 +2149,7 @@ index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e8
+
+ /**
+ * List of rule entries
++ *
+ * @return rules
+ */
+ @Contract(pure = true)
@@ -2122,6 +2176,7 @@ index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e8
+
+ /**
+ * Blocks to match.
++ *
+ * @return blocks
+ */
+ @NonNull RegistryKeySet<BlockType> blockTypes();
@@ -2130,13 +2185,15 @@ index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e8
+ * Overrides the mining speed if present and matched.
+ * <p>
+ * {@code true} will cause the block to mine at its most efficient speed, and drop items if the targeted block requires that.
++ *
+ * @return speed override
+ */
+ @Nullable Float speed();
+
+ /**
+ * Overrides whether this tool is considered 'correct' if present and matched.
-+ * @return
++ *
++ * @return a tri-state
+ */
+ @NonNull TriState correctForDrops();
+ }
@@ -2146,6 +2203,7 @@ index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e8
+
+ /**
+ * Controls the amount of durability to remove each time a block is mined with this tool.
++ *
+ * @param damage durability to remove
+ * @return self
+ */
@@ -2154,6 +2212,7 @@ index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e8
+
+ /**
+ * Controls mining speed to use if no rules match and don't override mining speed.
++ *
+ * @param speed mining speed
+ * @return self
+ */
@@ -2162,6 +2221,7 @@ index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e8
+
+ /**
+ * Adds a rule to the tool that controls the breaking speed / damage per block if matched.
++ *
+ * @param rule rule
+ * @return self
+ */
@@ -2170,6 +2230,7 @@ index 0000000000000000000000000000000000000000..d5ab454e3012e310ca48a69fba3bd5e8
+
+ /**
+ * Adds rules to the tool that control the breaking speed / damage per block if matched.
++ *
+ * @param rules rules
+ * @return self
+ */
@@ -2212,10 +2273,10 @@ index 0000000000000000000000000000000000000000..ecd1130152d0bac324cfd1feeb38b86e
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/WritableBookContent.java b/src/main/java/io/papermc/paper/datacomponent/item/WritableBookContent.java
new file mode 100644
-index 0000000000000000000000000000000000000000..5e4909f44f902058cd41560c3efccef5049b2402
+index 0000000000000000000000000000000000000000..a0c78a0bff8512792797d2268cdd9c4e774abf89
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/WritableBookContent.java
-@@ -0,0 +1,62 @@
+@@ -0,0 +1,67 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -2237,6 +2298,7 @@ index 0000000000000000000000000000000000000000..5e4909f44f902058cd41560c3efccef5
+
+ /**
+ * Holds the pages that can be written to for this component.
++ *
+ * @return pages, as filtered objects
+ */
+ @Contract(pure = true)
@@ -2247,6 +2309,7 @@ index 0000000000000000000000000000000000000000..5e4909f44f902058cd41560c3efccef5
+
+ /**
+ * Adds a page that can be written to for this builder.
++ *
+ * @param page page
+ * @return self
+ */
@@ -2255,6 +2318,7 @@ index 0000000000000000000000000000000000000000..5e4909f44f902058cd41560c3efccef5
+
+ /**
+ * Adds pages that can be written to for this builder.
++ *
+ * @param pages pages
+ * @return self
+ */
@@ -2263,6 +2327,7 @@ index 0000000000000000000000000000000000000000..5e4909f44f902058cd41560c3efccef5
+
+ /**
+ * Adds a filterable page that can be written to for this builder.
++ *
+ * @param page page
+ * @return self
+ */
@@ -2271,6 +2336,7 @@ index 0000000000000000000000000000000000000000..5e4909f44f902058cd41560c3efccef5
+
+ /**
+ * Adds filterable pages that can be written to for this builder.
++ *
+ * @param pages pages
+ * @return self
+ */
@@ -2280,10 +2346,10 @@ index 0000000000000000000000000000000000000000..5e4909f44f902058cd41560c3efccef5
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/WrittenBookContent.java b/src/main/java/io/papermc/paper/datacomponent/item/WrittenBookContent.java
new file mode 100644
-index 0000000000000000000000000000000000000000..de4927fa96ed799d2c80f47958dc5c4baa508ce4
+index 0000000000000000000000000000000000000000..07d5d7b5e281790e108a0a3acfd007782d175461
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/WrittenBookContent.java
-@@ -0,0 +1,92 @@
+@@ -0,0 +1,96 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.datacomponent.ComponentBuilder;
@@ -2315,6 +2381,7 @@ index 0000000000000000000000000000000000000000..de4927fa96ed799d2c80f47958dc5c4b
+
+ /**
+ * Title of this book.
++ *
+ * @return title
+ */
+ @Contract(pure = true)
@@ -2322,6 +2389,7 @@ index 0000000000000000000000000000000000000000..de4927fa96ed799d2c80f47958dc5c4b
+
+ /**
+ * Player name of the author of this book.
++ *
+ * @return author
+ */
+ @Contract(pure = true)
@@ -2329,6 +2397,7 @@ index 0000000000000000000000000000000000000000..de4927fa96ed799d2c80f47958dc5c4b
+
+ /**
+ * The number of times this book has been copied (0 = original)
++ *
+ * @return generation
+ */
+ @Contract(pure = true)
@@ -2340,6 +2409,7 @@ index 0000000000000000000000000000000000000000..de4927fa96ed799d2c80f47958dc5c4b
+ /**
+ * If the chat components in this book have already been resolved (entity selectors, scores substituted)
+ * If false, will be resolved when opened by a player
++ *
+ * @return resolved
+ */
+ @Contract(pure = true)
@@ -2370,10 +2440,10 @@ index 0000000000000000000000000000000000000000..de4927fa96ed799d2c80f47958dc5c4b
+ @NonNull Builder addPages(@NonNull Collection<@NonNull ? extends ComponentLike> page);
+
+ @Contract(value = "_ -> this", mutates = "this")
-+ @NonNull Builder addPageFiltered(@NonNull Filtered<@NonNull ? extends ComponentLike> page);
++ @NonNull Builder addFilteredPage(@NonNull Filtered<@NonNull ? extends ComponentLike> page);
+
+ @Contract(value = "_ -> this", mutates = "this")
-+ @NonNull Builder addPagesFiltered(@NonNull Collection<@NonNull Filtered<@NonNull ? extends ComponentLike>> pages);
++ @NonNull Builder addFilteredPages(@NonNull Collection<@NonNull Filtered<@NonNull ? extends ComponentLike>> pages);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/package-info.java b/src/main/java/io/papermc/paper/datacomponent/package-info.java
diff --git a/patches/server/1026-WIP-DataComponent-API.patch b/patches/server/1026-WIP-DataComponent-API.patch
index 970b57a1e5..f482a04dc3 100644
--- a/patches/server/1026-WIP-DataComponent-API.patch
+++ b/patches/server/1026-WIP-DataComponent-API.patch
@@ -355,16 +355,17 @@ index 0000000000000000000000000000000000000000..b5db510f1e641bba6d6a70c920921a77
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ComponentTypesBridgesImpl.java b/src/main/java/io/papermc/paper/datacomponent/item/ComponentTypesBridgesImpl.java
new file mode 100644
-index 0000000000000000000000000000000000000000..ba148b249d0e29debca93bc146caabf3016a1d57
+index 0000000000000000000000000000000000000000..c0d3af2b26390d48c3c5d825c31bc9fc07cdd778
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/ComponentTypesBridgesImpl.java
-@@ -0,0 +1,177 @@
+@@ -0,0 +1,179 @@
+package io.papermc.paper.datacomponent.item;
+
+import io.papermc.paper.registry.set.RegistryKeySet;
+import io.papermc.paper.util.Filtered;
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.util.TriState;
++import org.bukkit.JukeboxSong;
+import org.bukkit.block.BlockType;
+import org.bukkit.inventory.meta.trim.ArmorTrim;
+import org.bukkit.map.MapCursor;
@@ -472,8 +473,8 @@ index 0000000000000000000000000000000000000000..ba148b249d0e29debca93bc146caabf3
+ }
+
+ @Override
-+ public JukeboxPlayable.Builder jukeboxPlayable() {
-+ return new PaperJukeboxPlayable.BuilderImpl();
++ public JukeboxPlayable.Builder jukeboxPlayable(JukeboxSong song) {
++ return new PaperJukeboxPlayable.BuilderImpl(song);
+ }
+
+ @Override
@@ -483,6 +484,7 @@ index 0000000000000000000000000000000000000000..ba148b249d0e29debca93bc146caabf3
+
+ @Override
+ public Tool.Rule rule(final RegistryKeySet<BlockType> blockTypes, final @Nullable Float speed, final TriState correctForDrops) {
++ //Preconditions.checkArgument(speed == null || speed > 0, "Speed must be positive");
+ return new PaperItemTool.PaperRule(blockTypes, speed, correctForDrops);
+ }
+
@@ -711,7 +713,7 @@ index 0000000000000000000000000000000000000000..09335d46724831478fe396905a0f8d21
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperBundleContents.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperBundleContents.java
new file mode 100644
-index 0000000000000000000000000000000000000000..ff2f4400ce971c6934672267c02e99a3d16500d7
+index 0000000000000000000000000000000000000000..4865acd021f1d00b0f8fcecc6b2836e68a1d622c
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperBundleContents.java
@@ -0,0 +1,52 @@
@@ -719,6 +721,7 @@ index 0000000000000000000000000000000000000000..ff2f4400ce971c6934672267c02e99a3
+
+import java.util.ArrayList;
+import java.util.List;
++import com.google.common.base.Preconditions;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.util.Handleable;
+import org.bukkit.inventory.ItemStack;
@@ -749,15 +752,14 @@ index 0000000000000000000000000000000000000000..ff2f4400ce971c6934672267c02e99a3
+
+ @Override
+ public BundleContents.Builder add(final ItemStack stack) {
++ Preconditions.checkArgument(!stack.isEmpty(), "Item stack cannot be empty!");
+ this.items.add(CraftItemStack.asNMSCopy(stack));
+ return this;
+ }
+
+ @Override
+ public BundleContents.Builder addAll(final List<ItemStack> stacks) {
-+ for (final ItemStack item : stacks) {
-+ this.items.add(CraftItemStack.asNMSCopy(item));
-+ }
++ stacks.forEach(this::add);
+ return this;
+ }
+
@@ -769,7 +771,7 @@ index 0000000000000000000000000000000000000000..ff2f4400ce971c6934672267c02e99a3
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperChargedProjectiles.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperChargedProjectiles.java
new file mode 100644
-index 0000000000000000000000000000000000000000..4e05a8a3609f50d1e33c7babee6be5b6bc27237a
+index 0000000000000000000000000000000000000000..c81b13d88f19ac272ab27986722543490ce38bec
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperChargedProjectiles.java
@@ -0,0 +1,51 @@
@@ -777,6 +779,7 @@ index 0000000000000000000000000000000000000000..4e05a8a3609f50d1e33c7babee6be5b6
+
+import java.util.ArrayList;
+import java.util.List;
++import com.google.common.base.Preconditions;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.util.Handleable;
+import org.bukkit.inventory.ItemStack;
@@ -805,16 +808,15 @@ index 0000000000000000000000000000000000000000..4e05a8a3609f50d1e33c7babee6be5b6
+ private final List<net.minecraft.world.item.ItemStack> items = new ArrayList<>();
+
+ @Override
-+ public ChargedProjectiles.Builder add(final ItemStack itemStack) {
-+ this.items.add(CraftItemStack.asNMSCopy(itemStack));
++ public ChargedProjectiles.Builder add(final ItemStack stack) {
++ Preconditions.checkArgument(!stack.isEmpty(), "Item stack cannot be empty!");
++ this.items.add(CraftItemStack.asNMSCopy(stack));
+ return this;
+ }
+
+ @Override
-+ public ChargedProjectiles.Builder addAll(final List<ItemStack> itemStacks) {
-+ for (final ItemStack item : itemStacks) {
-+ this.items.add(CraftItemStack.asNMSCopy(item));
-+ }
++ public ChargedProjectiles.Builder addAll(final List<ItemStack> stacks) {
++ stacks.forEach(this::add);
+ return this;
+ }
+
@@ -930,10 +932,10 @@ index 0000000000000000000000000000000000000000..da22c58bcbf3e03686961f5a5127edef
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperFireworks.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperFireworks.java
new file mode 100644
-index 0000000000000000000000000000000000000000..9671617b9cf3c0e97b1b200d1f44b85a3c17a38b
+index 0000000000000000000000000000000000000000..34ff8431ae588c1bfe0f6c7aa621de7357f084b7
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperFireworks.java
-@@ -0,0 +1,79 @@
+@@ -0,0 +1,80 @@
+package io.papermc.paper.datacomponent.item;
+
+import com.google.common.base.Preconditions;
@@ -979,6 +981,7 @@ index 0000000000000000000000000000000000000000..9671617b9cf3c0e97b1b200d1f44b85a
+
+ @Override
+ public Fireworks.Builder flightDuration(final int duration) {
++ Preconditions.checkArgument(duration >= 0 && duration <= 0xFF, "duration must be an unsigned byte ([%s, %s]) but was %s", 0, 0xFF, duration);
+ this.duration = duration;
+ return this;
+ }
@@ -1015,25 +1018,24 @@ index 0000000000000000000000000000000000000000..9671617b9cf3c0e97b1b200d1f44b85a
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperFoodProperties.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperFoodProperties.java
new file mode 100644
-index 0000000000000000000000000000000000000000..17e40b72146afcc7eb79a536855d22244b3bb899
+index 0000000000000000000000000000000000000000..1404f97914767e57c59e33cb0b0cdffa9c4b50c0
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperFoodProperties.java
-@@ -0,0 +1,146 @@
+@@ -0,0 +1,152 @@
+package io.papermc.paper.datacomponent.item;
+
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
-+import java.util.function.Function;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.potion.CraftPotionUtil;
+import org.bukkit.craftbukkit.util.Handleable;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionEffect;
+import org.checkerframework.checker.nullness.qual.NonNull;
++import org.checkerframework.checker.nullness.qual.Nullable;
+import org.checkerframework.framework.qual.DefaultQualifier;
-+import org.jetbrains.annotations.Nullable;
+
+import static io.papermc.paper.datacomponent.item.ComponentUtils.addAndConvert;
+import static io.papermc.paper.datacomponent.item.ComponentUtils.transform;
@@ -1073,7 +1075,7 @@ index 0000000000000000000000000000000000000000..17e40b72146afcc7eb79a536855d2224
+
+ @Override
+ public @Nullable ItemStack usingConvertsTo() {
-+ return this.impl.usingConvertsTo().map((Function<net.minecraft.world.item.ItemStack, ItemStack>) itemStack -> CraftItemStack.asCraftMirror(itemStack.copy())).orElse(null);
++ return this.impl.usingConvertsTo().map(item -> CraftItemStack.asCraftMirror(item.copy())).orElse(null);
+ }
+
+ @Override
@@ -1113,7 +1115,7 @@ index 0000000000000000000000000000000000000000..17e40b72146afcc7eb79a536855d2224
+ private float eatSeconds = net.minecraft.world.food.FoodProperties.DEFAULT_EAT_SECONDS;
+ private float saturation = 0;
+ private int nutrition = 0;
-+ private Optional<net.minecraft.world.item.ItemStack> itemStack = Optional.empty();
++ private @Nullable ItemStack convertedStack;
+
+ @Override
+ public FoodProperties.Builder canAlwaysEat(final boolean canAlwaysEat) {
@@ -1142,8 +1144,8 @@ index 0000000000000000000000000000000000000000..17e40b72146afcc7eb79a536855d2224
+ }
+
+ @Override
-+ public @NonNull Builder usingConvertsTo(@org.jetbrains.annotations.Nullable final ItemStack itemStack) {
-+ this.itemStack = Optional.ofNullable(itemStack).map(CraftItemStack::asNMSCopy);
++ public FoodProperties.Builder usingConvertsTo(final @Nullable ItemStack itemStack) {
++ this.convertedStack = itemStack;
+ return this;
+ }
+
@@ -1154,20 +1156,27 @@ index 0000000000000000000000000000000000000000..17e40b72146afcc7eb79a536855d2224
+ }
+
+ @Override
-+ public Builder addAllEffects(final List<PossibleEffect> effects) {
++ public FoodProperties.Builder addAllEffects(final List<PossibleEffect> effects) {
+ addAndConvert(this.possibleEffects, effects, ef -> ((PossibleEffectImpl) ef).possibleEffect());
+ return this;
+ }
+
+ @Override
+ public FoodProperties build() {
-+ return new PaperFoodProperties(new net.minecraft.world.food.FoodProperties(this.nutrition, this.saturation, this.canAlwaysEat, this.eatSeconds, this.itemStack, this.possibleEffects));
++ return new PaperFoodProperties(new net.minecraft.world.food.FoodProperties(
++ this.nutrition,
++ this.saturation,
++ this.canAlwaysEat,
++ this.eatSeconds,
++ Optional.ofNullable(this.convertedStack).map(CraftItemStack::asNMSCopy),
++ this.possibleEffects
++ ));
+ }
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperItemAdventurePredicate.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperItemAdventurePredicate.java
new file mode 100644
-index 0000000000000000000000000000000000000000..cde2b0abffbd717984c57e649a91842c30b5360d
+index 0000000000000000000000000000000000000000..a6368dc4288b5a4cb60c0cb006f8a5072afc1e2f
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperItemAdventurePredicate.java
@@ -0,0 +1,78 @@
@@ -1220,7 +1229,7 @@ index 0000000000000000000000000000000000000000..cde2b0abffbd717984c57e649a91842c
+ }
+
+ @Override
-+ public @NonNull @Unmodifiable List<@NonNull BlockPredicate> modifiers() {
++ public @NonNull @Unmodifiable List<@NonNull BlockPredicate> predicates() {
+ return this.predicates;
+ }
+
@@ -1232,7 +1241,7 @@ index 0000000000000000000000000000000000000000..cde2b0abffbd717984c57e649a91842c
+ @Override
+ public @NonNull Builder addPredicate(@NonNull final BlockPredicate predicate) {
+ this.predicates.add(new net.minecraft.advancements.critereon.BlockPredicate(Optional.ofNullable(predicate.blocks()).map(
-+ typedKeys -> PaperRegistrySets.convertToNms(Registries.BLOCK, BuiltInRegistries.BUILT_IN_CONVERSIONS.lookup(), typedKeys)
++ blocks -> PaperRegistrySets.convertToNms(Registries.BLOCK, BuiltInRegistries.BUILT_IN_CONVERSIONS.lookup(), blocks)
+ ), Optional.empty(), Optional.empty()));
+ return this;
+ }
@@ -1325,10 +1334,10 @@ index 0000000000000000000000000000000000000000..d96be0ea89094d080ab81722d36af99a
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperItemAttributeModifiers.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperItemAttributeModifiers.java
new file mode 100644
-index 0000000000000000000000000000000000000000..ea0c8b76a577a4be9588154f8192257a7bc2b1ed
+index 0000000000000000000000000000000000000000..11cdc84f9d64e0c38d116eff0ca767e9de421990
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperItemAttributeModifiers.java
-@@ -0,0 +1,91 @@
+@@ -0,0 +1,96 @@
+package io.papermc.paper.datacomponent.item;
+
+import com.google.common.base.Preconditions;
@@ -1339,6 +1348,7 @@ index 0000000000000000000000000000000000000000..ea0c8b76a577a4be9588154f8192257a
+import org.bukkit.craftbukkit.CraftEquipmentSlot;
+import org.bukkit.craftbukkit.attribute.CraftAttribute;
+import org.bukkit.craftbukkit.attribute.CraftAttributeInstance;
++import org.bukkit.craftbukkit.util.CraftNamespacedKey;
+import org.bukkit.craftbukkit.util.Handleable;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
@@ -1389,9 +1399,12 @@ index 0000000000000000000000000000000000000000..ea0c8b76a577a4be9588154f8192257a
+ @Override
+ public ItemAttributeModifiers.Builder addModifier(final Attribute attribute, final AttributeModifier attributeModifier) {
+ Preconditions.checkArgument(
-+ this.entries.stream().noneMatch(e -> e.modifier().id().equals(attributeModifier.getUniqueId())),
-+ "Cannot add 2 modifiers with identical UUIDs"
++ this.entries.stream().noneMatch(e ->
++ e.modifier().id().equals(CraftNamespacedKey.toMinecraft(attributeModifier.getKey())) && e.attribute().is(CraftNamespacedKey.toMinecraft(attribute.getKey()))),
++ "Cannot add 2 modifiers with identical keys on the same attribute (modifier %s for attribute %s)",
++ attributeModifier.getKey(), attribute.getKey()
+ );
++
+ this.entries.add(new net.minecraft.world.item.component.ItemAttributeModifiers.Entry(
+ CraftAttribute.bukkitToMinecraftHolder(attribute),
+ CraftAttributeInstance.convert(attributeModifier),
@@ -1411,6 +1424,7 @@ index 0000000000000000000000000000000000000000..ea0c8b76a577a4be9588154f8192257a
+ if (this.entries.isEmpty()) {
+ return new PaperItemAttributeModifiers(net.minecraft.world.item.component.ItemAttributeModifiers.EMPTY);
+ }
++
+ return new PaperItemAttributeModifiers(
+ new net.minecraft.world.item.component.ItemAttributeModifiers(
+ this.entries,
@@ -1491,7 +1505,7 @@ index 0000000000000000000000000000000000000000..eb86427206b7f5d38c40bfe26358dc6a
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperItemEnchantments.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperItemEnchantments.java
new file mode 100644
-index 0000000000000000000000000000000000000000..bbf1524f95f8672dff239f17303e858bdc8fd5b3
+index 0000000000000000000000000000000000000000..1f1ae514250c586479da5d2bc45f39447679879d
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperItemEnchantments.java
@@ -0,0 +1,92 @@
@@ -1552,9 +1566,9 @@ index 0000000000000000000000000000000000000000..bbf1524f95f8672dff239f17303e858b
+ @Override
+ public ItemEnchantments.Builder add(final Enchantment enchantment, final int level) {
+ Preconditions.checkArgument(
-+ level <= 255,
-+ "level must be not be greater than %s, was %s",
-+ 255,
++ level >= 1 && level <= net.minecraft.world.item.enchantment.Enchantment.MAX_LEVEL,
++ "level must be included in [%s, %s], but was %s",
++ 1, net.minecraft.world.item.enchantment.Enchantment.MAX_LEVEL,
+ level
+ );
+ this.enchantments.put(enchantment, level);
@@ -1680,10 +1694,10 @@ index 0000000000000000000000000000000000000000..a7374010c21d87a225805d2c7dce2c5d
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperItemTool.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperItemTool.java
new file mode 100644
-index 0000000000000000000000000000000000000000..f6338542768b4f5c29919bc69d825a9cc18d7989
+index 0000000000000000000000000000000000000000..02cf3613bb93266c19988f3af47ecf992e573a36
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperItemTool.java
-@@ -0,0 +1,98 @@
+@@ -0,0 +1,97 @@
+package io.papermc.paper.datacomponent.item;
+
+import java.util.ArrayList;
@@ -1698,9 +1712,8 @@ index 0000000000000000000000000000000000000000..f6338542768b4f5c29919bc69d825a9c
+import org.bukkit.block.BlockType;
+import org.bukkit.craftbukkit.util.Handleable;
+import org.checkerframework.checker.nullness.qual.NonNull;
++import org.checkerframework.checker.nullness.qual.Nullable;
+import org.checkerframework.framework.qual.DefaultQualifier;
-+import org.jetbrains.annotations.NotNull;
-+import org.jetbrains.annotations.Nullable;
+
+import static io.papermc.paper.datacomponent.item.ComponentUtils.transform;
+
@@ -1739,7 +1752,7 @@ index 0000000000000000000000000000000000000000..f6338542768b4f5c29919bc69d825a9c
+
+
+ // TODO maybe move to API as package-private so they can create Entry objects? not sure if needed
-+ public record PaperRule(RegistryKeySet<BlockType> blockTypes, @Nullable Float speed, @NotNull TriState correctForDrops) implements Rule {
++ public record PaperRule(RegistryKeySet<BlockType> blockTypes, @Nullable Float speed, @NonNull TriState correctForDrops) implements Rule {
+ }
+
+ static final class BuilderImpl implements Builder {
@@ -1749,7 +1762,7 @@ index 0000000000000000000000000000000000000000..f6338542768b4f5c29919bc69d825a9c
+ private float miningSpeed = 1.0F;
+
+ @Override
-+ public @NonNull Builder damagePerBlock(@NonNull final int damage) {
++ public @NonNull Builder damagePerBlock(final int damage) {
+ this.damage = damage;
+ return this;
+ }
@@ -1765,7 +1778,7 @@ index 0000000000000000000000000000000000000000..f6338542768b4f5c29919bc69d825a9c
+ this.rules.add(new net.minecraft.world.item.component.Tool.Rule(
+ PaperRegistrySets.convertToNms(Registries.BLOCK, BuiltInRegistries.BUILT_IN_CONVERSIONS.lookup(), rule.blockTypes()),
+ Optional.ofNullable(rule.speed()),
-+ Optional.of(rule.correctForDrops().toBoolean())
++ Optional.ofNullable(rule.correctForDrops().toBoolean())
+ ));
+ return this;
+ }
@@ -1784,10 +1797,10 @@ index 0000000000000000000000000000000000000000..f6338542768b4f5c29919bc69d825a9c
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperJukeboxPlayable.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperJukeboxPlayable.java
new file mode 100644
-index 0000000000000000000000000000000000000000..754532e7ecc86d4494af58658a4d96d2d5c64876
+index 0000000000000000000000000000000000000000..4eedbfc337fc3c937845268546dcd2f58ca0d789
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperJukeboxPlayable.java
-@@ -0,0 +1,59 @@
+@@ -0,0 +1,61 @@
+package io.papermc.paper.datacomponent.item;
+
+import net.minecraft.world.item.EitherHolder;
@@ -1797,8 +1810,6 @@ index 0000000000000000000000000000000000000000..754532e7ecc86d4494af58658a4d96d2
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
-+import static io.papermc.paper.datacomponent.item.ComponentUtils.transform;
-+
+@DefaultQualifier(NonNull.class)
+public record PaperJukeboxPlayable(
+ net.minecraft.world.item.JukeboxPlayable impl
@@ -1820,15 +1831,19 @@ index 0000000000000000000000000000000000000000..754532e7ecc86d4494af58658a4d96d2
+ }
+
+ @Override
-+ public JukeboxSong jukeboxSong() {
-+ return CraftJukeboxSong.minecraftHolderToBukkit(this.impl.song().holder().get());
++ public @NonNull JukeboxSong jukeboxSong() {
++ return this.impl.song().holder().map(CraftJukeboxSong::minecraftHolderToBukkit).orElseThrow();
+ }
+
+ static final class BuilderImpl implements Builder {
+
-+ private JukeboxSong song = null;
++ private JukeboxSong song;
+ private boolean showInTooltip = true;
+
++ public BuilderImpl(JukeboxSong song) {
++ this.song = song;
++ }
++
+ @Override
+ public Builder showInTooltip(final boolean showInTooltip) {
+ this.showInTooltip = showInTooltip;
@@ -1849,10 +1864,10 @@ index 0000000000000000000000000000000000000000..754532e7ecc86d4494af58658a4d96d2
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperLockCode.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperLockCode.java
new file mode 100644
-index 0000000000000000000000000000000000000000..07c87bef8903014a955ca61bd797f16310468716
+index 0000000000000000000000000000000000000000..0737a3d3ed9a325f0cf232278de0098d711032ab
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperLockCode.java
-@@ -0,0 +1,37 @@
+@@ -0,0 +1,40 @@
+package io.papermc.paper.datacomponent.item;
+
+import org.bukkit.craftbukkit.util.Handleable;
@@ -1876,7 +1891,7 @@ index 0000000000000000000000000000000000000000..07c87bef8903014a955ca61bd797f163
+
+ static final class BuilderImpl implements LockCode.Builder {
+
-+ private String lock = "";
++ private String lock = net.minecraft.world.LockCode.NO_LOCK.key();
+
+ @Override
+ public LockCode.Builder lock(final String code) {
@@ -1886,22 +1901,24 @@ index 0000000000000000000000000000000000000000..07c87bef8903014a955ca61bd797f163
+
+ @Override
+ public LockCode build() {
++ if (this.lock.isEmpty()) {
++ return new PaperLockCode(net.minecraft.world.LockCode.NO_LOCK);
++ }
+ return new PaperLockCode(new net.minecraft.world.LockCode(this.lock));
+ }
+ }
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperLodestoneTracker.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperLodestoneTracker.java
new file mode 100644
-index 0000000000000000000000000000000000000000..27605ab59141e0b995d83eaafc4b83056fe3eb61
+index 0000000000000000000000000000000000000000..fea818b24e2833033ef70c1ca825de814eccaf61
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperLodestoneTracker.java
-@@ -0,0 +1,56 @@
+@@ -0,0 +1,58 @@
+package io.papermc.paper.datacomponent.item;
+
+import java.util.Optional;
-+import net.minecraft.core.GlobalPos;
+import org.bukkit.Location;
-+import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper;
++import org.bukkit.craftbukkit.util.CraftLocation;
+import org.bukkit.craftbukkit.util.Handleable;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
@@ -1919,7 +1936,7 @@ index 0000000000000000000000000000000000000000..27605ab59141e0b995d83eaafc4b8305
+
+ @Override
+ public @Nullable Location location() {
-+ return this.impl.target().map(CraftMemoryMapper::fromNms).orElse(null);
++ return this.impl.target().map(CraftLocation::fromGlobalPos).orElse(null);
+ }
+
+ @Override
@@ -1929,12 +1946,12 @@ index 0000000000000000000000000000000000000000..27605ab59141e0b995d83eaafc4b8305
+
+ static final class BuilderImpl implements LodestoneTracker.Builder {
+
-+ private Optional<GlobalPos> pos = Optional.empty();
++ private @Nullable Location pos;
+ private boolean tracked = true;
+
+ @Override
+ public LodestoneTracker.Builder location(final @Nullable Location location) {
-+ this.pos = Optional.ofNullable(location).map(CraftMemoryMapper::toNms);
++ this.pos = location;
+ return this;
+ }
+
@@ -1947,7 +1964,10 @@ index 0000000000000000000000000000000000000000..27605ab59141e0b995d83eaafc4b8305
+ @Override
+ public LodestoneTracker build() {
+ return new PaperLodestoneTracker(
-+ new net.minecraft.world.item.component.LodestoneTracker(this.pos, this.tracked)
++ new net.minecraft.world.item.component.LodestoneTracker(
++ Optional.ofNullable(this.pos).map(CraftLocation::toGlobalPos),
++ this.tracked
++ )
+ );
+ }
+ }
@@ -2094,7 +2114,7 @@ index 0000000000000000000000000000000000000000..e74819d2e8c3819419d5ddbe686fddf3
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperMapItemColor.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperMapItemColor.java
new file mode 100644
-index 0000000000000000000000000000000000000000..14656be5a23dac70460499a79f60b8f3b3d86f1f
+index 0000000000000000000000000000000000000000..86c9366220bf0b31551d66751ade98bf5c2a3ef0
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperMapItemColor.java
@@ -0,0 +1,38 @@
@@ -2117,7 +2137,7 @@ index 0000000000000000000000000000000000000000..14656be5a23dac70460499a79f60b8f3
+
+ @Override
+ public Color mapColor() {
-+ return Color.fromRGB(this.impl.rgb() & 0xFFFFFF); // only track the rgb values of the integer
++ return Color.fromRGB(this.impl.rgb() & 0x00FFFFFF); // skip alpha channel
+ }
+
+ static final class BuilderImpl implements Builder {
@@ -2138,7 +2158,7 @@ index 0000000000000000000000000000000000000000..14656be5a23dac70460499a79f60b8f3
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperPotDecorations.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperPotDecorations.java
new file mode 100644
-index 0000000000000000000000000000000000000000..f79cc0bfd543c755a445e140c8ceacb302f53ada
+index 0000000000000000000000000000000000000000..3bf2538dff070f48b735bafe88a23e6ee22fbc6d
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperPotDecorations.java
@@ -0,0 +1,87 @@
@@ -2191,30 +2211,30 @@ index 0000000000000000000000000000000000000000..f79cc0bfd543c755a445e140c8ceacb3
+ private @Nullable Material front;
+
+ @Override
-+ public PotDecorations.Builder back(final @Nullable Material item) {
-+ Preconditions.checkArgument(item == null || item.isItem(), "%s is not an item", item);
-+ this.back = item;
++ public PotDecorations.Builder back(final @Nullable Material back) {
++ Preconditions.checkArgument(back == null || back.isItem(), "%s is not an item", back);
++ this.back = back;
+ return this;
+ }
+
+ @Override
-+ public PotDecorations.Builder left(final @Nullable Material item) {
-+ Preconditions.checkArgument(item == null || item.isItem(), "%s is not an item", item);
-+ this.left = item;
++ public PotDecorations.Builder left(final @Nullable Material left) {
++ Preconditions.checkArgument(left == null || left.isItem(), "%s is not an item", left);
++ this.left = left;
+ return this;
+ }
+
+ @Override
-+ public PotDecorations.Builder right(final @Nullable Material item) {
-+ Preconditions.checkArgument(item == null || item.isItem(), "%s is not an item", item);
-+ this.right = item;
++ public PotDecorations.Builder right(final @Nullable Material right) {
++ Preconditions.checkArgument(right == null || right.isItem(), "%s is not an item", right);
++ this.right = right;
+ return this;
+ }
+
+ @Override
-+ public PotDecorations.Builder front(final @Nullable Material item) {
-+ Preconditions.checkArgument(item == null || item.isItem(), "%s is not an item", item);
-+ this.front = item;
++ public PotDecorations.Builder front(final @Nullable Material front) {
++ Preconditions.checkArgument(front == null || front.isItem(), "%s is not an item", front);
++ this.front = front;
+ return this;
+ }
+
@@ -2327,7 +2347,7 @@ index 0000000000000000000000000000000000000000..a18cbe16298ad944e1fff4f4c5576ae3
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperResolvableProfile.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperResolvableProfile.java
new file mode 100644
-index 0000000000000000000000000000000000000000..11498b8e6cb2db2cfb67ac3fbd4217c681d79f11
+index 0000000000000000000000000000000000000000..d469fd6e0cd853c275ad263c832623f3b0b24cf5
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperResolvableProfile.java
@@ -0,0 +1,105 @@
@@ -2388,21 +2408,21 @@ index 0000000000000000000000000000000000000000..11498b8e6cb2db2cfb67ac3fbd4217c6
+ static final class BuilderImpl implements ResolvableProfile.Builder {
+
+ private final PropertyMap propertyMap = new PropertyMap();
-+ private Optional<String> name = Optional.empty();
-+ private Optional<UUID> uuid = Optional.empty();
++ private @Nullable String name;
++ private @Nullable UUID uuid;
+
+ @Override
+ public ResolvableProfile.Builder name(final @Nullable String name) {
+ final int length = name == null ? 0 : name.length();
+ Preconditions.checkArgument(name == null || length <= 16, "name cannot be more than 16 characters, was %s", length);
+ Preconditions.checkArgument(name == null || StringUtil.isValidPlayerName(name), "name cannot include invalid characters, was %s", name);
-+ this.name = Optional.ofNullable(name);
++ this.name = name;
+ return this;
+ }
+
+ @Override
+ public ResolvableProfile.Builder uuid(final @Nullable UUID uuid) {
-+ this.uuid = Optional.ofNullable(uuid);
++ this.uuid = uuid;
+ return this;
+ }
+
@@ -2427,10 +2447,10 @@ index 0000000000000000000000000000000000000000..11498b8e6cb2db2cfb67ac3fbd4217c6
+
+ @Override
+ public ResolvableProfile build() {
-+ Preconditions.checkState(this.name.isPresent() || this.uuid.isPresent(), "Must specify at least a name or uuid");
++ Preconditions.checkState(this.name != null || this.uuid != null || !this.propertyMap.isEmpty(), "Must specify at least a name, a uuid or a property");
+ return new PaperResolvableProfile(new net.minecraft.world.item.component.ResolvableProfile(
-+ this.name,
-+ this.uuid,
++ Optional.ofNullable(this.name),
++ Optional.ofNullable(this.uuid),
+ this.propertyMap
+ ));
+ }
@@ -2731,7 +2751,7 @@ index 0000000000000000000000000000000000000000..5c8249525613bfb2ddca470f27947fbe
+}
diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PaperWrittenBookContent.java b/src/main/java/io/papermc/paper/datacomponent/item/PaperWrittenBookContent.java
new file mode 100644
-index 0000000000000000000000000000000000000000..4925f031e41d6b62e597fd1d558b38ec94956f4e
+index 0000000000000000000000000000000000000000..afb79f06d38fe0eeacfb5473b2f6d4e8cc869e83
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datacomponent/item/PaperWrittenBookContent.java
@@ -0,0 +1,190 @@
@@ -2895,7 +2915,7 @@ index 0000000000000000000000000000000000000000..4925f031e41d6b62e597fd1d558b38ec
+ }
+
+ @Override
-+ public WrittenBookContent.Builder addPageFiltered(final Filtered<? extends ComponentLike> page) {
++ public WrittenBookContent.Builder addFilteredPage(final Filtered<? extends ComponentLike> page) {
+ final Component raw = page.raw().asComponent();
+ validatePageLength(raw);
+ @Nullable Component filtered = null;
@@ -2908,8 +2928,8 @@ index 0000000000000000000000000000000000000000..4925f031e41d6b62e597fd1d558b38ec
+ }
+
+ @Override
-+ public WrittenBookContent.Builder addPagesFiltered(final Collection<Filtered<? extends ComponentLike>> pages) {
-+ pages.forEach(this::addPageFiltered);
++ public WrittenBookContent.Builder addFilteredPages(final Collection<Filtered<? extends ComponentLike>> pages) {
++ pages.forEach(this::addFilteredPage);
+ return this;
+ }
+
@@ -3180,6 +3200,27 @@ index 4d97024bb05ab815409fc25c5924903868cc3945..a1839baaef752f54efeebb982b160396
if (this.hasDisplayName()) {
itemTag.put(CraftMetaItem.NAME, this.displayName);
}
+diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftLocation.java b/src/main/java/org/bukkit/craftbukkit/util/CraftLocation.java
+index 097996d3955ab5126b71f7bff1dd2c62becb5ffd..0797ef29b76564491351042ce47e3d4500490bef 100644
+--- a/src/main/java/org/bukkit/craftbukkit/util/CraftLocation.java
++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftLocation.java
+@@ -40,6 +40,16 @@ public final class CraftLocation {
+ return new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ }
+
++ // Paper start
++ public static net.minecraft.core.GlobalPos toGlobalPos(Location location) {
++ return net.minecraft.core.GlobalPos.of(((org.bukkit.craftbukkit.CraftWorld) location.getWorld()).getHandle().dimension(), toBlockPosition(location));
++ }
++
++ public static Location fromGlobalPos(net.minecraft.core.GlobalPos globalPos) {
++ return new org.bukkit.Location(net.minecraft.server.MinecraftServer.getServer().getLevel(globalPos.dimension()).getWorld(), globalPos.pos().getX(), globalPos.pos().getY(), globalPos.pos().getZ());
++ }
++ // Paper end
++
+ public static Vec3 toVec3D(Location location) {
+ return new Vec3(location.getX(), location.getY(), location.getZ());
+ }
diff --git a/src/main/resources/META-INF/services/io.papermc.paper.datacomponent.item.ComponentTypesBridge b/src/main/resources/META-INF/services/io.papermc.paper.datacomponent.item.ComponentTypesBridge
new file mode 100644
index 0000000000000000000000000000000000000000..1c1fcbbacc3881e088d64a7a840b3f3e31706c0f