DEATH_PROTECTION = valued("death_protection");
++ /**
++ * Stores list of enchantments and their levels for an Enchanted Book.
++ * Unlike {@link #ENCHANTMENTS}, the effects provided by enchantments
++ * do not apply from this component.
++ *
++ * If not present on an Enchanted Book, it will not work in an anvil.
++ *
++ * Has an undefined behaviour if present on an item that is not an Enchanted Book
++ * (currently the presence of this component allows enchantments from {@link #ENCHANTMENTS}
++ * to be applied as if this item was an Enchanted Book).
++ *
++ * @see #ENCHANTMENTS
++ */
++ public static final DataComponentType.Valued STORED_ENCHANTMENTS = valued("stored_enchantments");
++ /**
++ * Represents a color applied to a dyeable item (in the {@link io.papermc.paper.registry.keys.tags.ItemTypeTagKeys#DYEABLE} item tag).
++ */
++ public static final DataComponentType.Valued DYED_COLOR = valued("dyed_color");
++ /**
++ * Represents the tint of the decorations on the Filled Map item.
++ */
++ public static final DataComponentType.Valued MAP_COLOR = valued("map_color");
++ /**
++ * References the shared map state holding map contents and markers for a Filled Map.
++ */
++ public static final DataComponentType.Valued MAP_ID = valued("map_id");
++ /**
++ * Holds a list of markers to be placed on a Filled Map (used for Explorer Maps).
++ */
++ public static final DataComponentType.Valued MAP_DECORATIONS = valued("map_decorations");
++ /**
++ * Internal map item state used in the map crafting recipe.
++ */
++ public static final DataComponentType.Valued MAP_POST_PROCESSING = valued("map_post_processing");
++ /**
++ * Holds all projectiles that have been loaded into a Crossbow.
++ * If not present, the Crossbow is not charged.
++ */
++ public static final DataComponentType.Valued CHARGED_PROJECTILES = valued("charged_projectiles");
++ /**
++ * Holds all items stored inside a Bundle.
++ * If removed, items cannot be added to the Bundle.
++ */
++ public static final DataComponentType.Valued BUNDLE_CONTENTS = valued("bundle_contents");
++ /**
++ * Holds the contents of a potion (Potion, Splash Potion, Lingering Potion),
++ * or potion applied to a Tipped Arrow.
++ */
++ public static final DataComponentType.Valued POTION_CONTENTS = valued("potion_contents");
++ /**
++ * Holds the effects that will be applied when consuming Suspicious Stew.
++ */
++ public static final DataComponentType.Valued SUSPICIOUS_STEW_EFFECTS = valued("suspicious_stew_effects");
++ /**
++ * Holds the contents in a Book and Quill.
++ */
++ public static final DataComponentType.Valued WRITABLE_BOOK_CONTENT = valued("writable_book_content");
++ /**
++ * Holds the contents and metadata of a Written Book.
++ */
++ public static final DataComponentType.Valued WRITTEN_BOOK_CONTENT = valued("written_book_content");
++ /**
++ * Holds the trims applied to an item in recipes
++ */
++ public static final DataComponentType.Valued TRIM = valued("trim");
++ // debug_stick_state - Block Property API
++ // entity_data
++ // bucket_entity_data
++ // block_entity_data
++ /**
++ * Holds the instrument type used by a Goat Horn.
++ */
++ public static final DataComponentType.Valued INSTRUMENT = valued("instrument");
++ /**
++ * Controls the amplifier amount for an Ominous Bottle's Bad Omen effect.
++ */
++ public static final DataComponentType.Valued OMINOUS_BOTTLE_AMPLIFIER = valued("ominous_bottle_amplifier");
++ /**
++ * List of recipes that should be unlocked when using the Knowledge Book item.
++ */
++ public static final DataComponentType.Valued JUKEBOX_PLAYABLE = valued("jukebox_playable");
++ public static final DataComponentType.Valued> RECIPES = valued("recipes");
++ /**
++ * If present, specifies that the Compass is a Lodestone Compass.
++ */
++ public static final DataComponentType.Valued LODESTONE_TRACKER = valued("lodestone_tracker");
++ /**
++ * Stores the explosion crafted in a Firework Star.
++ */
++ public static final DataComponentType.Valued FIREWORK_EXPLOSION = valued("firework_explosion");
++ /**
++ * Stores all explosions crafted into a Firework Rocket, as well as flight duration.
++ */
++ public static final DataComponentType.Valued FIREWORKS = valued("fireworks");
++ /**
++ * Controls the skin displayed on a Player Head.
++ */
++ public static final DataComponentType.Valued PROFILE = valued("profile");
++ /**
++ * Controls the sound played by a Player Head when placed on a Note Block.
++ */
++ public static final DataComponentType.Valued NOTE_BLOCK_SOUND = valued("note_block_sound");
++ /**
++ * Stores the additional patterns applied to a Banner or Shield.
++ */
++ public static final DataComponentType.Valued BANNER_PATTERNS = valued("banner_patterns");
++ /**
++ * Stores the base color for a Shield.
++ */
++ public static final DataComponentType.Valued BASE_COLOR = valued("base_color");
++ /**
++ * Stores the Sherds applied to each side of a Decorated Pot.
++ */
++ public static final DataComponentType.Valued POT_DECORATIONS = valued("pot_decorations");
++ /**
++ * Holds the contents of container blocks (Chests, Shulker Boxes) in item form.
++ */
++ public static final DataComponentType.Valued CONTAINER = valued("container");
++ /**
++ * Holds block state properties to apply when placing a block.
++ */
++ public static final DataComponentType.Valued BLOCK_DATA = valued("block_state");
++ // bees
++ /**
++ * Holds the lock state of a container-like block,
++ * copied to container block when placed.
++ *
++ * An item with a custom name of the same value must be used
++ * to open this container.
++ */
++ public static final DataComponentType.Valued LOCK = valued("lock");
++ /**
++ * Holds the unresolved loot table and seed of a container-like block.
++ */
++ public static final DataComponentType.Valued CONTAINER_LOOT = valued("container_loot");
++
++ private static DataComponentType.NonValued unvalued(final String name) {
++ return (DataComponentType.NonValued) requireNonNull(Registry.DATA_COMPONENT_TYPE.get(NamespacedKey.minecraft(name)), name + " unvalued data component type couldn't be found, this is a bug.");
++ }
++
++ @SuppressWarnings("unchecked")
++ private static DataComponentType.Valued valued(final String name) {
++ return (DataComponentType.Valued) requireNonNull(Registry.DATA_COMPONENT_TYPE.get(NamespacedKey.minecraft(name)), name + " valued data component type couldn't be found, this is a bug.");
++ }
++
++ private DataComponentTypes() {
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/BannerPatternLayers.java b/src/main/java/io/papermc/paper/datacomponent/item/BannerPatternLayers.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..2f9b006c906aa07af705b7cd0cb8d36b160e6edf
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/BannerPatternLayers.java
+@@ -0,0 +1,71 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.Arrays;
++import java.util.List;
++import org.bukkit.block.banner.Pattern;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the layers of patterns on a banner.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#BANNER_PATTERNS
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface BannerPatternLayers {
++
++ @Contract(value = "_ -> new", pure = true)
++ static BannerPatternLayers bannerPatternLayers(final Pattern ...patterns) {
++ return bannerPatternLayers(Arrays.asList(patterns));
++ }
++
++ @Contract(value = "_ -> new", pure = true)
++ static BannerPatternLayers bannerPatternLayers(final List patterns) {
++ return bannerPatternLayers().addAll(patterns).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static BannerPatternLayers.Builder bannerPatternLayers() {
++ return ItemComponentTypesBridge.bridge().bannerPatternLayers();
++ }
++
++ /**
++ * Gets the patterns on the banner.
++ *
++ * @return the patterns
++ */
++ @Contract(pure = true)
++ @Unmodifiable List patterns();
++
++ /**
++ * Builder for {@link BannerPatternLayers}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Adds a pattern to the banner.
++ *
++ * @param pattern the pattern
++ * @return the builder for chaining
++ * @see #patterns()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder add(Pattern pattern);
++
++ /**
++ * Adds multiple patterns to the banner.
++ *
++ * @param patterns the patterns
++ * @return the builder for chaining
++ * @see #patterns()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addAll(List patterns);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/BlockItemDataProperties.java b/src/main/java/io/papermc/paper/datacomponent/item/BlockItemDataProperties.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..65f1bc8d1bea0042dca9683c439561132dbeea5c
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/BlockItemDataProperties.java
+@@ -0,0 +1,51 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.bukkit.block.BlockType;
++import org.bukkit.block.data.BlockData;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the {@link BlockData} properties of a block item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCK_DATA
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface BlockItemDataProperties {
++
++ @Contract(value = "-> new", pure = true)
++ static BlockItemDataProperties.Builder blockItemStateProperties() {
++ return ItemComponentTypesBridge.bridge().blockItemStateProperties();
++ }
++
++ /**
++ * Creates a new {@link BlockData} instance for the given {@link BlockType}.
++ *
++ * @param blockType the block type
++ * @return the block data
++ */
++ @Contract(pure = true)
++ BlockData createBlockData(BlockType blockType);
++
++ /**
++ * Applies the properties to the given {@link BlockData}. Doesn't
++ * mutate the parameter, but returns a new instance with the properties applied.
++ *
++ * @param blockData the block data to apply the properties to
++ * @return the block data with the properties applied
++ */
++ @Contract(pure = true)
++ BlockData applyTo(BlockData blockData);
++
++ /**
++ * Builder for {@link BlockItemDataProperties}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++ // building this requires BlockProperty API, so an empty builder for now (essentially read-only)
++ }
++}
+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..de43ba7f000e5aae35add19651cf23ab803f97e9
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/BundleContents.java
+@@ -0,0 +1,71 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.Arrays;
++import java.util.List;
++import org.bukkit.inventory.ItemStack;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds all items stored inside of a Bundle.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#BUNDLE_CONTENTS
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface BundleContents {
++
++ @Contract(value = "_ -> new", pure = true)
++ static BundleContents bundleContents(final ItemStack ...contents) {
++ return bundleContents(Arrays.asList(contents));
++ }
++
++ @Contract(value = "_ -> new", pure = true)
++ static BundleContents bundleContents(final List contents) {
++ return ItemComponentTypesBridge.bridge().bundleContents().addAll(contents).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static BundleContents.Builder bundleContents() {
++ return ItemComponentTypesBridge.bridge().bundleContents();
++ }
++
++ /**
++ * Lists the items that are currently stored inside of this component.
++ *
++ * @return items
++ */
++ @Contract(value = "-> new", pure = true)
++ @Unmodifiable List contents();
++
++ /**
++ * Builder for {@link BundleContents}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Adds an item to this builder.
++ *
++ * @param stack item
++ * @return the builder for chaining
++ * @see #contents()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder add(ItemStack stack);
++
++ /**
++ * Adds items to this builder.
++ *
++ * @param stacks items
++ * @return the builder for chaining
++ * @see #contents()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addAll(List stacks);
++ }
++}
+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..09240fe94f7f48d4d24e99cc362aed55b13d31b5
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ChargedProjectiles.java
+@@ -0,0 +1,71 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.Arrays;
++import java.util.List;
++import org.bukkit.inventory.ItemStack;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds all projectiles that have been loaded into a Crossbow.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#CHARGED_PROJECTILES
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ChargedProjectiles {
++
++ @Contract(value = "_ -> new", pure = true)
++ static ChargedProjectiles chargedProjectiles(final ItemStack ...projectiles) {
++ return chargedProjectiles(Arrays.asList(projectiles));
++ }
++
++ @Contract(value = "_ -> new", pure = true)
++ static ChargedProjectiles chargedProjectiles(final List projectiles) {
++ return chargedProjectiles().addAll(projectiles).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static ChargedProjectiles.Builder chargedProjectiles() {
++ return ItemComponentTypesBridge.bridge().chargedProjectiles();
++ }
++
++ /**
++ * Lists the projectiles that are currently loaded into this component.
++ *
++ * @return the loaded projectiles
++ */
++ @Contract(value = "-> new", pure = true)
++ @Unmodifiable List projectiles();
++
++ /**
++ * Builder for {@link ChargedProjectiles}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Adds a projectile to be loaded in this builder.
++ *
++ * @param stack projectile
++ * @return the builder for chaining
++ * @see #projectiles()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder add(ItemStack stack);
++
++ /**
++ * Adds projectiles to be loaded in this builder.
++ *
++ * @param stacks projectiles
++ * @return the builder for chaining
++ * @see #projectiles()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addAll(List stacks);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/Consumable.java b/src/main/java/io/papermc/paper/datacomponent/item/Consumable.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..55ba9e1d09a35d9c9a034f928d6b9383517eb775
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/Consumable.java
+@@ -0,0 +1,70 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.BuildableDataComponent;
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect;
++import io.papermc.paper.datacomponent.item.consumable.ItemUseAnimation;
++import java.util.Collection;
++import java.util.List;
++import net.kyori.adventure.key.Key;
++import org.checkerframework.checker.index.qual.NonNegative;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the properties for this item for when it is consumed.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#CONSUMABLE
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface Consumable extends BuildableDataComponent {
++
++ @Contract(value = "-> new", pure = true)
++ static Consumable.Builder consumable() {
++ return ItemComponentTypesBridge.bridge().consumable();
++ }
++
++ @Contract(pure = true)
++ @NonNegative float consumeSeconds();
++
++ @Contract(pure = true)
++ ItemUseAnimation animation();
++
++ @Contract(pure = true)
++ Key sound();
++
++ @Contract(pure = true)
++ boolean hasConsumeParticles();
++
++ @Contract(pure = true)
++ @Unmodifiable List consumeEffects();
++
++ /**
++ * Builder for {@link Consumable}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder consumeSeconds(@NonNegative float consumeSeconds);
++
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder animation(ItemUseAnimation animation);
++
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder sound(Key sound);
++
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder hasConsumeParticles(boolean hasConsumeParticles);
++
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addEffect(ConsumeEffect effect);
++
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addEffects(Collection effects);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/CustomModelData.java b/src/main/java/io/papermc/paper/datacomponent/item/CustomModelData.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..d416c9d25b3ab88bf1e208c6faf92a8e2378c376
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/CustomModelData.java
+@@ -0,0 +1,28 @@
++package io.papermc.paper.datacomponent.item;
++
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the custom model data.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#CUSTOM_MODEL_DATA
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface CustomModelData {
++
++ @Contract(value = "_ -> new", pure = true)
++ static CustomModelData customModelData(final int id) {
++ return ItemComponentTypesBridge.bridge().customModelData(id);
++ }
++
++ /**
++ * Gets the custom model data id.
++ *
++ * @return the id
++ */
++ @Contract(pure = true)
++ int id();
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/DamageResistant.java b/src/main/java/io/papermc/paper/datacomponent/item/DamageResistant.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..6cbd73cb2a11f4858b44a2f57d2fe0acb1eb9fb5
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/DamageResistant.java
+@@ -0,0 +1,30 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.registry.tag.TagKey;
++import org.bukkit.damage.DamageType;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the contents of damage types that the item entity containing this item is invincible to.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#DAMAGE_RESISTANT
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface DamageResistant {
++
++ @Contract(value = "_ -> new", pure = true)
++ static DamageResistant damageResistant(final TagKey types) {
++ return ItemComponentTypesBridge.bridge().damageResistant(types);
++ }
++
++ /**
++ * The types that this damage type is invincible tp.
++ *
++ * @return item
++ */
++ @Contract(value = "-> new", pure = true)
++ TagKey types();
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/DeathProtection.java b/src/main/java/io/papermc/paper/datacomponent/item/DeathProtection.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..f2dd5407c7a91867308eff01f8753a207dbfac2b
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/DeathProtection.java
+@@ -0,0 +1,53 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect;
++import java.util.Arrays;
++import java.util.Collection;
++import java.util.List;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Sets whether this item should protect the entity upon death, and what effects should be played.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#DEATH_PROTECTION
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface DeathProtection {
++
++ @Contract(value = "_ -> new", pure = true)
++ static DeathProtection deathProtection(final ConsumeEffect ...deathEffects) {
++ return deathProtection(Arrays.asList(deathEffects));
++ }
++
++ @Contract(value = "_ -> new", pure = true)
++ static DeathProtection deathProtection(final List deathEffects) {
++ return deathProtection().addEffects(deathEffects).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static DeathProtection.Builder deathProtection() {
++ return ItemComponentTypesBridge.bridge().deathProtection();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ @Unmodifiable List deathEffects();
++
++ /**
++ * Builder for {@link DeathProtection}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addEffect(ConsumeEffect effect);
++
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addEffects(Collection effects);
++ }
++}
+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..d80581fc8b894cc4d4af9741244b1bb03468b263
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/DyedItemColor.java
+@@ -0,0 +1,53 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.bukkit.Color;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Represents a color applied to a dyeable item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#DYED_COLOR
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface DyedItemColor extends ShownInTooltip {
++
++ @Contract(value = "_, _ -> new", pure = true)
++ static DyedItemColor dyedItemColor(final Color color, final boolean showInTooltip) {
++ return dyedItemColor().color(color).showInTooltip(showInTooltip).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static DyedItemColor.Builder dyedItemColor() {
++ return ItemComponentTypesBridge.bridge().dyedItemColor();
++ }
++
++ /**
++ * Color of the item.
++ *
++ * @return color
++ */
++ @Contract(value = "-> new", pure = true)
++ Color color();
++
++ /**
++ * Builder for {@link DyedItemColor}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends ShownInTooltip.Builder, DataComponentBuilder {
++
++ /**
++ * Sets the color of this builder.
++ *
++ * @param color color
++ * @return the builder for chaining
++ * @see #color()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder color(Color color);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/Enchantable.java b/src/main/java/io/papermc/paper/datacomponent/item/Enchantable.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..91a17840755d652fa94cf357f1951efad644798c
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/Enchantable.java
+@@ -0,0 +1,30 @@
++package io.papermc.paper.datacomponent.item;
++
++import org.checkerframework.checker.index.qual.Positive;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds if an item is enchantable, allowing for enchantments of the type to be seen in an enchanting table.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#ENCHANTABLE
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface Enchantable {
++
++ @Contract(value = "_ -> new", pure = true)
++ static Enchantable enchantable(final @Positive int level) {
++ return ItemComponentTypesBridge.bridge().enchantable(level);
++ }
++
++ /**
++ * Gets the current enchantment value level allowed,
++ * a higher value allows enchantments with a higher cost to be picked.
++ *
++ * @return the value
++ */
++ @Contract(pure = true)
++ @Positive int value();
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/Equippable.java b/src/main/java/io/papermc/paper/datacomponent/item/Equippable.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..7d84217814bba4ce826e33755fee0d5c3b280009
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/Equippable.java
+@@ -0,0 +1,170 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.BuildableDataComponent;
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import io.papermc.paper.registry.set.RegistryKeySet;
++import net.kyori.adventure.key.Key;
++import org.bukkit.entity.EntityType;
++import org.bukkit.inventory.EquipmentSlot;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++import org.jspecify.annotations.Nullable;
++
++
++/**
++ * Holds the equippable properties of an item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#EQUIPPABLE
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface Equippable extends BuildableDataComponent {
++
++ /**
++ * Creates a new {@link Equippable.Builder} instance.
++ * @param slot The slot for the new equippable to be equippable in.
++ *
++ * @return a new builder
++ */
++ @Contract(value = "_ -> new", pure = true)
++ static Equippable.Builder equippable(final EquipmentSlot slot) {
++ return ItemComponentTypesBridge.bridge().equippable(slot);
++ }
++
++ /**
++ * Gets the equipment slot this item can be equipped in.
++ *
++ * @return the equipment slot
++ */
++ @Contract(pure = true)
++ EquipmentSlot slot();
++
++ /**
++ * Gets the equip sound key.
++ *
++ * @return the equip sound key
++ */
++ @Contract(pure = true)
++ Key equipSound();
++
++ /**
++ * Gets the model key if present.
++ *
++ * @return the model key or null
++ */
++ @Contract(pure = true)
++ @Nullable Key model();
++
++ /**
++ * Gets the camera overlay key if present.
++ *
++ * @return the camera overlay key or null
++ */
++ @Contract(pure = true)
++ @Nullable Key cameraOverlay();
++
++ /**
++ * Gets the set of allowed entities that can equip this item.
++ * May be null if all entities are allowed.
++ *
++ * @return the set of allowed entities
++ */
++ @Contract(pure = true)
++ @Nullable RegistryKeySet allowedEntities();
++
++ /**
++ * Checks if the item is dispensable.
++ *
++ * @return true if dispensable, false otherwise
++ */
++ @Contract(pure = true)
++ boolean dispensable();
++
++ /**
++ * Checks if the item is swappable.
++ *
++ * @return true if swappable, false otherwise
++ */
++ @Contract(pure = true)
++ boolean swappable();
++
++ /**
++ * Checks if the item takes damage when the wearer is hurt.
++ *
++ * @return true if it damages on hurt, false otherwise
++ */
++ @Contract(pure = true)
++ boolean damageOnHurt();
++
++ /**
++ * Builder for {@link Equippable}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets the equip sound key for this item.
++ *
++ * @param equipSound the equip sound key
++ * @return the builder for chaining
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder equipSound(Key equipSound);
++
++ /**
++ * Sets the model key for this item.
++ *
++ * @param model the model key, nullable
++ * @return the builder for chaining
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder model(@Nullable Key model);
++
++ /**
++ * Sets the camera overlay key for this item.
++ *
++ * @param cameraOverlay the camera overlay key, nullable
++ * @return the builder for chaining
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder cameraOverlay(@Nullable Key cameraOverlay);
++
++ /**
++ * Sets the allowed entities that can equip this item.
++ *
++ * @param allowedEntities the set of allowed entity types, or null if any
++ * @return the builder for chaining
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder allowedEntities(@Nullable RegistryKeySet allowedEntities);
++
++ /**
++ * Sets whether the item is dispensable.
++ *
++ * @param dispensable true if dispensable
++ * @return the builder for chaining
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder dispensable(boolean dispensable);
++
++ /**
++ * Sets whether the item is swappable.
++ *
++ * @param swappable true if swappable
++ * @return the builder for chaining
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder swappable(boolean swappable);
++
++ /**
++ * Sets whether the item takes damage when the wearer is hurt.
++ *
++ * @param damageOnHurt true if it damages on hurt
++ * @return the builder for chaining
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder damageOnHurt(boolean damageOnHurt);
++ }
++}
+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..72aa1b4bda2693e0cd78d93449dda23bd1b74062
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/Fireworks.java
+@@ -0,0 +1,84 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.List;
++import org.bukkit.FireworkEffect;
++import org.checkerframework.common.value.qual.IntRange;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Stores all explosions crafted into a Firework Rocket, as well as flight duration.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#FIREWORKS
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface Fireworks {
++
++ @Contract(value = "_, _ -> new", pure = true)
++ static Fireworks fireworks(final List effects, final int flightDuration) {
++ return fireworks().addEffects(effects).flightDuration(flightDuration).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static Fireworks.Builder fireworks() {
++ return ItemComponentTypesBridge.bridge().fireworks();
++ }
++
++ /**
++ * Lists the effects stored in this component.
++ *
++ * @return the effects
++ */
++ @Contract(pure = true)
++ @Unmodifiable List effects();
++
++ /**
++ * Number of gunpowder in this component.
++ *
++ * @return the flight duration
++ */
++ @Contract(pure = true)
++ @IntRange(from = 0, to = 255) int flightDuration();
++
++ /**
++ * Builder for {@link Fireworks}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets the number of gunpowder used in this builder.
++ *
++ * @param duration duration
++ * @return the builder for chaining
++ * @see #flightDuration()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder flightDuration(@IntRange(from = 0, to = 255) int duration);
++
++ /**
++ * Adds an explosion to this builder.
++ *
++ * @param effect effect
++ * @return the builder for chaining
++ * @see #effects()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addEffect(FireworkEffect effect);
++
++ /**
++ * Adds explosions to this builder.
++ *
++ * @param effects effects
++ * @return the builder for chaining
++ * @see #effects()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addEffects(List effects);
++ }
++}
+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..369208e15a0e7fc91a9505fef2097c4283445e4a
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/FoodProperties.java
+@@ -0,0 +1,87 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.BuildableDataComponent;
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.checkerframework.checker.index.qual.NonNegative;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the food properties of an item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#FOOD
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface FoodProperties extends BuildableDataComponent {
++
++ @Contract(value = "-> new", pure = true)
++ static FoodProperties.Builder food() {
++ return ItemComponentTypesBridge.bridge().food();
++ }
++
++ /**
++ * Number of food points to restore when eaten.
++ *
++ * @return the nutrition
++ */
++ @Contract(pure = true)
++ @NonNegative int nutrition();
++
++ /**
++ * Amount of saturation to restore when eaten.
++ *
++ * @return the saturation
++ */
++ @Contract(pure = true)
++ float saturation();
++
++ /**
++ * If {@code true}, this food can be eaten even if not hungry.
++ *
++ * @return can always be eaten
++ */
++ @Contract(pure = true)
++ boolean canAlwaysEat();
++
++ /**
++ * Builder for {@link FoodProperties}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Set if this food can always be eaten, even if the
++ * player is not hungry.
++ *
++ * @param canAlwaysEat true to allow always eating
++ * @return the builder for chaining
++ * @see #canAlwaysEat()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder canAlwaysEat(boolean canAlwaysEat);
++
++ /**
++ * Sets the saturation of the food.
++ *
++ * @param saturation the saturation
++ * @return the builder for chaining
++ * @see #saturation()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder saturation(float saturation);
++
++ /**
++ * Sets the nutrition of the food.
++ *
++ * @param nutrition the nutrition, must be non-negative
++ * @return the builder for chaining
++ * @see #nutrition()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder nutrition(@NonNegative int nutrition);
++
++ }
++}
+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..eefff688896d6705e09abf2f1423a8ba7db5d4c6
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemAdventurePredicate.java
+@@ -0,0 +1,70 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.block.BlockPredicate;
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.List;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Controls which blocks a player in Adventure mode can do a certain action with this item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#CAN_BREAK
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#CAN_PLACE_ON
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ItemAdventurePredicate extends ShownInTooltip {
++
++ @Contract(value = "_ -> new", pure = true)
++ static ItemAdventurePredicate itemAdventurePredicate(final BlockPredicate ...predicates) {
++ return itemAdventurePredicate(List.of(predicates));
++ }
++
++ @Contract(value = "_ -> new", pure = true)
++ static ItemAdventurePredicate itemAdventurePredicate(final List predicates) {
++ return itemAdventurePredicate().addPredicates(predicates).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static ItemAdventurePredicate.Builder itemAdventurePredicate() {
++ return ItemComponentTypesBridge.bridge().itemAdventurePredicate();
++ }
++
++ /**
++ * List of block predicates that control if the action is allowed.
++ *
++ * @return predicates
++ */
++ @Contract(pure = true)
++ @Unmodifiable List predicates();
++
++ /**
++ * Builder for {@link ItemAdventurePredicate}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends ShownInTooltip.Builder, DataComponentBuilder {
++ /**
++ * Adds a block predicate to this builder.
++ *
++ * @param predicate predicate
++ * @return the builder for chaining
++ * @see #predicates()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addPredicate(BlockPredicate predicate);
++
++ /**
++ * Adds block predicates to this builder.
++ *
++ * @param predicates predicates
++ * @return the builder for chaining
++ * @see #predicates()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addPredicates(List predicates);
++ }
++}
+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..0309ae59ab7945ddfb5410930d161e2ce3d1878a
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemArmorTrim.java
+@@ -0,0 +1,53 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.bukkit.inventory.meta.trim.ArmorTrim;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the trims applied to an item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#TRIM
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ItemArmorTrim extends ShownInTooltip {
++
++ @Contract(value = "_, _ -> new", pure = true)
++ static ItemArmorTrim itemArmorTrim(final ArmorTrim armorTrim, final boolean showInTooltip) {
++ return itemArmorTrim(armorTrim).showInTooltip(showInTooltip).build();
++ }
++
++ @Contract(value = "_ -> new", pure = true)
++ static ItemArmorTrim.Builder itemArmorTrim(final ArmorTrim armorTrim) {
++ return ItemComponentTypesBridge.bridge().itemArmorTrim(armorTrim);
++ }
++
++ /**
++ * Armor trim present on this item.
++ *
++ * @return trim
++ */
++ @Contract(pure = true)
++ ArmorTrim armorTrim();
++
++ /**
++ * Builder for {@link ItemArmorTrim}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends ShownInTooltip.Builder, DataComponentBuilder {
++
++ /**
++ * Sets the armor trim for this builder.
++ *
++ * @param armorTrim trim
++ * @return the builder for chaining
++ * @see #armorTrim()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder armorTrim(ArmorTrim armorTrim);
++ }
++}
+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..e33e709363ba4fea0a868e548f97ee5c89902653
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemAttributeModifiers.java
+@@ -0,0 +1,75 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.List;
++import org.bukkit.attribute.Attribute;
++import org.bukkit.attribute.AttributeModifier;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds attribute modifiers applied to any item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#ATTRIBUTE_MODIFIERS
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ItemAttributeModifiers extends ShownInTooltip {
++
++ @Contract(value = "-> new", pure = true)
++ static ItemAttributeModifiers.Builder itemAttributes() {
++ return ItemComponentTypesBridge.bridge().modifiers();
++ }
++
++ /**
++ * Lists the attribute modifiers that are present on this item.
++ *
++ * @return modifiers
++ */
++ @Contract(pure = true)
++ @Unmodifiable List modifiers();
++
++ /**
++ * Holds an attribute entry.
++ */
++ @ApiStatus.NonExtendable
++ interface Entry {
++
++ /**
++ * Gets the target attribute for the paired modifier.
++ *
++ * @return the attribute
++ */
++ @Contract(pure = true)
++ Attribute attribute();
++
++ /**
++ * The modifier for the paired attribute.
++ *
++ * @return the modifier
++ */
++ @Contract(pure = true)
++ AttributeModifier modifier();
++ }
++
++ /**
++ * Builder for {@link ItemAttributeModifiers}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends ShownInTooltip.Builder, DataComponentBuilder {
++
++ /**
++ * Adds a modifier to this builder.
++ *
++ * @param attribute attribute
++ * @param modifier modifier
++ * @return the builder for chaining
++ * @see #modifiers()
++ */
++ @Contract(value = "_, _ -> this", mutates = "this")
++ Builder addModifier(Attribute attribute, AttributeModifier modifier);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ItemComponentTypesBridge.java b/src/main/java/io/papermc/paper/datacomponent/item/ItemComponentTypesBridge.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..1097a6e0d0921abc6714017a123176ea23652ee0
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemComponentTypesBridge.java
+@@ -0,0 +1,112 @@
++package io.papermc.paper.datacomponent.item;
++
++import com.destroystokyo.paper.profile.PlayerProfile;
++import io.papermc.paper.registry.set.RegistryKeySet;
++import io.papermc.paper.registry.tag.TagKey;
++import io.papermc.paper.util.Filtered;
++import java.util.Optional;
++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.damage.DamageType;
++import org.bukkit.inventory.EquipmentSlot;
++import org.bukkit.inventory.ItemStack;
++import org.bukkit.inventory.ItemType;
++import org.bukkit.inventory.meta.trim.ArmorTrim;
++import org.bukkit.map.MapCursor;
++import org.jetbrains.annotations.ApiStatus;
++import org.jspecify.annotations.NullMarked;
++import org.jspecify.annotations.Nullable;
++
++@NullMarked
++@ApiStatus.Internal
++interface ItemComponentTypesBridge {
++
++ Optional BRIDGE = ServiceLoader.load(ItemComponentTypesBridge.class).findFirst();
++
++ static ItemComponentTypesBridge bridge() {
++ return BRIDGE.orElseThrow();
++ }
++
++ ChargedProjectiles.Builder chargedProjectiles();
++
++ PotDecorations.Builder potDecorations();
++
++ Unbreakable.Builder unbreakable();
++
++ ItemLore.Builder lore();
++
++ ItemEnchantments.Builder enchantments();
++
++ ItemAttributeModifiers.Builder modifiers();
++
++ FoodProperties.Builder food();
++
++ DyedItemColor.Builder dyedItemColor();
++
++ PotionContents.Builder potionContents();
++
++ BundleContents.Builder bundleContents();
++
++ SuspiciousStewEffects.Builder suspiciousStewEffects();
++
++ MapItemColor.Builder mapItemColor();
++
++ MapDecorations.Builder mapDecorations();
++
++ MapDecorations.DecorationEntry decorationEntry(MapCursor.Type type, double x, double z, float rotation);
++
++ SeededContainerLoot.Builder seededContainerLoot(Key lootTableKey);
++
++ WrittenBookContent.Builder writtenBookContent(Filtered title, String author);
++
++ WritableBookContent.Builder writeableBookContent();
++
++ ItemArmorTrim.Builder itemArmorTrim(ArmorTrim armorTrim);
++
++ LodestoneTracker.Builder lodestoneTracker();
++
++ Fireworks.Builder fireworks();
++
++ ResolvableProfile.Builder resolvableProfile();
++
++ ResolvableProfile resolvableProfile(PlayerProfile profile);
++
++ BannerPatternLayers.Builder bannerPatternLayers();
++
++ BlockItemDataProperties.Builder blockItemStateProperties();
++
++ ItemContainerContents.Builder itemContainerContents();
++
++ JukeboxPlayable.Builder jukeboxPlayable(JukeboxSong song);
++
++ Tool.Builder tool();
++
++ Tool.Rule rule(RegistryKeySet blocks, @Nullable Float speed, TriState correctForDrops);
++
++ ItemAdventurePredicate.Builder itemAdventurePredicate();
++
++ CustomModelData customModelData(int id);
++
++ MapId mapId(int id);
++
++ UseRemainder useRemainder(ItemStack itemStack);
++
++ Consumable.Builder consumable();
++
++ UseCooldown.Builder useCooldown(final float seconds);
++
++ DamageResistant damageResistant(TagKey types);
++
++ Enchantable enchantable(int level);
++
++ Repairable repairable(RegistryKeySet types);
++
++ Equippable.Builder equippable(EquipmentSlot slot);
++
++ DeathProtection.Builder deathProtection();
++
++ OminousBottleAmplifier ominousBottleAmplifier(int amplifier);
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ItemContainerContents.java b/src/main/java/io/papermc/paper/datacomponent/item/ItemContainerContents.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..72ab4707f85a06a05a238f52b0d165e359e1d66b
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemContainerContents.java
+@@ -0,0 +1,68 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.Arrays;
++import java.util.List;
++import org.bukkit.inventory.ItemStack;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the contents of an item container.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#CONTAINER
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ItemContainerContents {
++
++ @Contract(value = "_ -> new", pure = true)
++ static ItemContainerContents containerContents(final ItemStack ...contents) {
++ return containerContents(Arrays.asList(contents));
++ }
++
++ @Contract(value = "_ -> new", pure = true)
++ static ItemContainerContents containerContents(final List contents) {
++ return containerContents().addAll(contents).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static ItemContainerContents.Builder containerContents() {
++ return ItemComponentTypesBridge.bridge().itemContainerContents();
++ }
++
++ /**
++ * Gets the contents of the container.
++ *
++ * @return the contents
++ */
++ @Contract(value = "-> new", pure = true)
++ @Unmodifiable List contents();
++
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Adds an item stack to the container.
++ *
++ * @param stack the item stack
++ * @return the builder for chaining
++ * @see #contents()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder add(ItemStack stack);
++
++ /**
++ * Adds item stacks to the container.
++ *
++ * @param stacks the item stacks
++ * @return the builder for chaining
++ * @see #contents()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addAll(List stacks);
++ }
++}
+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..fca271ea198209bd48cd02f4476e89e5e3e9f396
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemEnchantments.java
+@@ -0,0 +1,68 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.Map;
++import org.bukkit.enchantments.Enchantment;
++import org.checkerframework.common.value.qual.IntRange;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Stores a list of enchantments and their levels on an item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#ENCHANTMENTS
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#STORED_ENCHANTMENTS
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ItemEnchantments extends ShownInTooltip {
++
++ @Contract(value = "_, _ -> new", pure = true)
++ static ItemEnchantments itemEnchantments(final Map enchantments, final boolean showInTooltip) {
++ return itemEnchantments().addAll(enchantments).showInTooltip(showInTooltip).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static ItemEnchantments.Builder itemEnchantments() {
++ return ItemComponentTypesBridge.bridge().enchantments();
++ }
++
++ /**
++ * Enchantments currently present on this item.
++ *
++ * @return enchantments
++ */
++ @Contract(pure = true)
++ @Unmodifiable Map enchantments();
++
++ /**
++ * Builder for {@link ItemEnchantments}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends ShownInTooltip.Builder, DataComponentBuilder {
++
++ /**
++ * Adds an enchantment with the given level to this component.
++ *
++ * @param enchantment enchantment
++ * @param level level
++ * @return the builder for chaining
++ * @see #enchantments()
++ */
++ @Contract(value = "_, _ -> this", mutates = "this")
++ Builder add(Enchantment enchantment, @IntRange(from = 1, to = 255) int level);
++
++ /**
++ * Adds enchantments with the given level to this component.
++ *
++ * @param enchantments enchantments
++ * @return the builder for chaining
++ * @see #enchantments()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addAll(Map 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..3be62f6005e0343c3a6ebd04e3ee824e0b969113
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ItemLore.java
+@@ -0,0 +1,84 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.List;
++import net.kyori.adventure.text.Component;
++import net.kyori.adventure.text.ComponentLike;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Additional lines to include in an item's tooltip.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#LORE
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ItemLore {
++
++ @Contract(value = "_ -> new", pure = true)
++ static ItemLore lore(final List extends ComponentLike> lines) {
++ return lore().lines(lines).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static ItemLore.Builder lore() {
++ return ItemComponentTypesBridge.bridge().lore();
++ }
++
++ /**
++ * Lists the components that are added to an item's tooltip.
++ *
++ * @return component list
++ */
++ @Contract(pure = true)
++ @Unmodifiable List lines();
++
++ /**
++ * Lists the styled components (example: italicized and purple) that are added to an item's tooltip.
++ *
++ * @return component list
++ */
++ @Contract(pure = true)
++ @Unmodifiable List styledLines();
++
++ /**
++ * Builder for {@link ItemLore}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets the components of this lore.
++ *
++ * @param lines components
++ * @return the builder for chaining
++ * @see #lines()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder lines(List extends ComponentLike> lines);
++
++ /**
++ * Adds a component to the lore.
++ *
++ * @param line component
++ * @return the builder for chaining
++ * @see #lines()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addLine(ComponentLike line);
++
++ /**
++ * Adds components to the lore.
++ *
++ * @param lines components
++ * @return the builder for chaining
++ * @see #lines()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addLines(List extends ComponentLike> lines);
++ }
++}
+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..c59942df7101c7630eabeb247b9690b9c4c76da4
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/JukeboxPlayable.java
+@@ -0,0 +1,43 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.bukkit.JukeboxSong;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the jukebox song for an item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#JUKEBOX_PLAYABLE
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface JukeboxPlayable extends ShownInTooltip {
++
++ @Contract(value = "_ -> new", pure = true)
++ static JukeboxPlayable.Builder jukeboxPlayable(final JukeboxSong song) {
++ return ItemComponentTypesBridge.bridge().jukeboxPlayable(song);
++ }
++
++ @Contract(pure = true)
++ JukeboxSong jukeboxSong();
++
++ /**
++ * Builder for {@link JukeboxPlayable}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends ShownInTooltip.Builder, DataComponentBuilder {
++
++ /**
++ * Sets the jukebox song.
++ *
++ * @param song the song
++ * @return the builder for chaining
++ * @see #jukeboxSong()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder jukeboxSong(JukeboxSong song);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/LockCode.java b/src/main/java/io/papermc/paper/datacomponent/item/LockCode.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..42cfb5c6cd5ad4c6475def221eb653b9d4dfe568
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/LockCode.java
+@@ -0,0 +1,22 @@
++package io.papermc.paper.datacomponent.item;
++
++import org.jetbrains.annotations.ApiStatus;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the lock code for an item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#LOCK
++ */
++@NullMarked
++@ApiStatus.NonExtendable
++@ApiStatus.Experimental
++public interface LockCode {
++
++ // @Contract(value = "_ -> new", pure = true)
++ // static LockCode lockCode(final String code) {
++ // return ItemComponentTypesBridge.bridge().lockCode(code);
++ // }
++ //
++ // @Contract(pure = true)
++ // String key();
++}
+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..b919672ceea74ae09324653847b30fde293054d8
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/LodestoneTracker.java
+@@ -0,0 +1,72 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.bukkit.Location;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++import org.jspecify.annotations.Nullable;
++
++/**
++ * If present, specifies the target Lodestone that a Compass should point towards.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#LODESTONE_TRACKER
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface LodestoneTracker {
++
++ @Contract(value = "_, _ -> new", pure = true)
++ static LodestoneTracker lodestoneTracker(final @Nullable Location location, final boolean tracked) {
++ return lodestoneTracker().location(location).tracked(tracked).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static LodestoneTracker.Builder lodestoneTracker() {
++ return ItemComponentTypesBridge.bridge().lodestoneTracker();
++ }
++
++ /**
++ * The location that the compass should point towards.
++ *
++ * @return location
++ */
++ @Contract(value = "-> new", pure = true)
++ @Nullable Location location();
++
++ /**
++ * If {@code true}, when the Lodestone at the target position is removed, the component will be removed.
++ *
++ * @return tracked
++ */
++ @Contract(pure = true)
++ boolean tracked();
++
++ /**
++ * Builder for {@link LodestoneTracker}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets the location to point towards for this builder.
++ *
++ * @param location location to point towards
++ * @return the builder for chaining
++ * @see #location()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder location(@Nullable Location location);
++
++ /**
++ * Sets if this location lodestone is tracked for this builder.
++ *
++ * @param tracked is tracked
++ * @return the builder for chaining
++ * @see #tracked()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder tracked(boolean tracked);
++ }
++}
+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..d1674197d3663a876c37589dc22c3b40a8790972
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/MapDecorations.java
+@@ -0,0 +1,121 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.Map;
++import org.bukkit.map.MapCursor;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++import org.jspecify.annotations.Nullable;
++
++/**
++ * Holds a list of markers to be placed on a Filled Map (used for Explorer Maps).
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#MAP_DECORATIONS
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface MapDecorations {
++
++ @Contract(value = "_ -> new", pure = true)
++ static MapDecorations mapDecorations(final Map entries) {
++ return mapDecorations().putAll(entries).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static MapDecorations.Builder mapDecorations() {
++ return ItemComponentTypesBridge.bridge().mapDecorations();
++ }
++
++ /**
++ * Gets the decoration entry with the given id.
++ *
++ * @param id id
++ * @return decoration entry, or {@code null} if not present
++ */
++ @Contract(pure = true)
++ @Nullable DecorationEntry getDecoration(String id);
++
++ /**
++ * Gets the decoration entries.
++ *
++ * @return the decoration entries
++ */
++ @Contract(pure = true)
++ @Unmodifiable Map decorations();
++
++ /**
++ * Decoration present on the map.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface DecorationEntry {
++
++ @Contract(value = "_, _, _, _ -> new", pure = true)
++ static DecorationEntry of(final MapCursor.Type type, final double x, final double z, final float rotation) {
++ return ItemComponentTypesBridge.bridge().decorationEntry(type, x, z, rotation);
++ }
++
++ /**
++ * Type of decoration.
++ *
++ * @return type
++ */
++ @Contract(pure = true)
++ MapCursor.Type type();
++
++ /**
++ * X world coordinate of the decoration.
++ *
++ * @return x coordinate
++ */
++ @Contract(pure = true)
++ double x();
++
++ /**
++ * Z world coordinate of the decoration.
++ *
++ * @return z coordinate
++ */
++ @Contract(pure = true)
++ double z();
++
++ /**
++ * Clockwise rotation from north in degrees.
++ *
++ * @return rotation
++ */
++ @Contract(pure = true)
++ float rotation();
++ }
++
++ /**
++ * Builder for {@link MapDecorations}.
++ */
++ @ApiStatus.NonExtendable
++ @ApiStatus.Experimental
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Puts the decoration with the given id in this builder.
++ *
++ * @param id id
++ * @param entry decoration
++ * @return the builder for chaining
++ * @see #decorations()
++ */
++ @Contract(value = "_, _ -> this", mutates = "this")
++ MapDecorations.Builder put(String id, DecorationEntry entry);
++
++ /**
++ * Puts all the decoration with the given id in this builder.
++ *
++ * @param entries decorations
++ * @return the builder for chaining
++ * @see #decorations()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ MapDecorations.Builder putAll(Map entries);
++ }
++}
+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..045bfe0ce5080b57a40be03a65b1a2aaf9089120
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/MapId.java
+@@ -0,0 +1,28 @@
++package io.papermc.paper.datacomponent.item;
++
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * References the shared map state holding map contents and markers for a Filled Map.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#MAP_ID
++ */
++@NullMarked
++@ApiStatus.NonExtendable
++@ApiStatus.Experimental
++public interface MapId {
++
++ @Contract(value = "_ -> new", pure = true)
++ static MapId mapId(final int id) {
++ return ItemComponentTypesBridge.bridge().mapId(id);
++ }
++
++ /**
++ * The map id.
++ *
++ * @return id
++ */
++ @Contract(pure = true)
++ int id();
++}
+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..87845d19a25ed2ae79b868fcfe40b88a2dc83f97
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/MapItemColor.java
+@@ -0,0 +1,43 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.bukkit.Color;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Represents the tint of the decorations on the Filled Map item.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#MAP_COLOR
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface MapItemColor {
++
++ @Contract(value = "-> new", pure = true)
++ static MapItemColor.Builder mapItemColor() {
++ return ItemComponentTypesBridge.bridge().mapItemColor();
++ }
++
++ /**
++ * The tint to apply.
++ *
++ * @return color
++ */
++ Color color();
++
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets the tint color of this map.
++ *
++ * @param color tint color
++ * @return the builder for chaining
++ * @see #color()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder color(Color color);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/OminousBottleAmplifier.java b/src/main/java/io/papermc/paper/datacomponent/item/OminousBottleAmplifier.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..4f16e08f04c2cea24f3cb132ff21f4bdd6b70582
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/OminousBottleAmplifier.java
+@@ -0,0 +1,29 @@
++package io.papermc.paper.datacomponent.item;
++
++import org.checkerframework.common.value.qual.IntRange;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the ominous bottle amplifier.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#OMINOUS_BOTTLE_AMPLIFIER
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface OminousBottleAmplifier {
++
++ @Contract(value = "_ -> new", pure = true)
++ static OminousBottleAmplifier amplifier(final @IntRange(from = 0, to = 4) int amplifier) {
++ return ItemComponentTypesBridge.bridge().ominousBottleAmplifier(amplifier);
++ }
++
++ /**
++ * Gets the bottle amplifier.
++ *
++ * @return the amplifier
++ */
++ @Contract(pure = true)
++ @IntRange(from = 0, to = 4) int amplifier();
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/PotDecorations.java b/src/main/java/io/papermc/paper/datacomponent/item/PotDecorations.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..6da78b8735a6cadd1282fa2fafd8b0f74f087fb4
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/PotDecorations.java
+@@ -0,0 +1,109 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.bukkit.inventory.ItemType;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++import org.jspecify.annotations.Nullable;
++
++// CONTRIBUTORS: LEAVE THIS AS ITEM TYPE!!!
++/**
++ * Holds the item types for the decorations on a flower pot.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#POT_DECORATIONS
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface PotDecorations {
++
++ @Contract(value = "_, _, _, _ -> new", pure = true)
++ static PotDecorations potDecorations(final @Nullable ItemType back, final @Nullable ItemType left, final @Nullable ItemType right, final @Nullable ItemType front) {
++ return potDecorations().back(back).left(left).right(right).front(front).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static PotDecorations.Builder potDecorations() {
++ return ItemComponentTypesBridge.bridge().potDecorations();
++ }
++
++ /**
++ * Get the item type for the back.
++ *
++ * @return the back item type.
++ */
++ @Contract(pure = true)
++ @Nullable ItemType back();
++
++ /**
++ * Get the item type for the left.
++ *
++ * @return the left item type.
++ */
++ @Contract(pure = true)
++ @Nullable ItemType left();
++
++ /**
++ * Get the item type for the right.
++ *
++ * @return the right item type.
++ */
++ @Contract(pure = true)
++ @Nullable ItemType right();
++
++ /**
++ * Get the item type for the front.
++ *
++ * @return the front item type.
++ */
++ @Contract(pure = true)
++ @Nullable ItemType front();
++
++ /**
++ * Builder for {@link PotDecorations}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Set the {@link ItemType} for the back.
++ *
++ * @param back item for the back
++ * @return the builder for chaining
++ * @see #back()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder back(@Nullable ItemType back);
++
++ /**
++ * Set the {@link ItemType} for the left.
++ *
++ * @param left item for the left
++ * @return the builder for chaining
++ * @see #left()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder left(@Nullable ItemType left);
++
++ /**
++ * Set the {@link ItemType} for the right.
++ *
++ * @param right item for the right
++ * @return the builder for chaining
++ * @see #right()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder right(@Nullable ItemType right);
++
++ /**
++ * Set the {@link ItemType} for the front.
++ *
++ * @param front item for the front
++ * @return the builder for chaining
++ * @see #front()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder front(@Nullable ItemType front);
++ }
++}
+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..7bfb093d6802828499fb06be1d900f41bd52daba
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/PotionContents.java
+@@ -0,0 +1,120 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.List;
++import org.bukkit.Color;
++import org.bukkit.potion.PotionEffect;
++import org.bukkit.potion.PotionType;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++import org.jspecify.annotations.Nullable;
++
++/**
++ * Holds the contents of a potion (Potion, Splash Potion, Lingering Potion), or potion applied to a Tipped Arrow.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#POTION_CONTENTS
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface PotionContents {
++
++ @Contract(value = "-> new", pure = true)
++ static PotionContents.Builder potionContents() { // can't name it just "enchantments"
++ return ItemComponentTypesBridge.bridge().potionContents();
++ }
++
++ /**
++ * The potion type in this item: the item will inherit all effects from this.
++ *
++ * @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 {@code null} if not present
++ * @apiNote alpha channel of the color is only relevant
++ * for Tipped Arrow
++ */
++ @Contract(pure = true)
++ @Nullable Color customColor();
++
++ /**
++ * Additional list of effect instances that this item should apply.
++ *
++ * @return effects
++ */
++ @Contract(pure = true)
++ @Unmodifiable List customEffects();
++
++ /**
++ * Overrides the visual name of the potion.
++ *
++ * @return name override, or {@code null} if not present
++ * @apiNote This is used in the display of tipped arrow and potion items.
++ */
++ @Contract(pure = true)
++ @Nullable String customName();
++
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets the potion type for this builder.
++ *
++ * @param type builder
++ * @return the builder for chaining
++ * @see #potion()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder potion(@Nullable PotionType type);
++
++ /**
++ * Sets the color override for this builder.
++ *
++ * @param color color
++ * @return the builder for chaining
++ * @see #customColor()
++ * @apiNote alpha channel of the color is supported only for Tipped Arrow
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder customColor(@Nullable Color color);
++
++ /**
++ * Sets the name override for this builder.
++ *
++ * @param name name
++ * @return the builder for chaining
++ * @see #customName()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder customName(@Nullable String name);
++
++ /**
++ * Adds a custom effect instance to this builder.
++ *
++ * @param effect effect
++ * @see #customEffects()
++ * @return the builder for chaining
++ * @see #customEffects()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addCustomEffect(PotionEffect effect);
++
++ /**
++ * Adds custom effect instances to this builder.
++ *
++ * @param effects effects
++ * @see #customEffects()
++ * @return the builder for chaining
++ * @see #customEffects()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addCustomEffects(List effects);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/Repairable.java b/src/main/java/io/papermc/paper/datacomponent/item/Repairable.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..ff84d9123aab0ad2f93b397e20a37f21894547a3
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/Repairable.java
+@@ -0,0 +1,30 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.registry.set.RegistryKeySet;
++import org.bukkit.inventory.ItemType;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds if this item is repairable, and what item types it can be repaired with.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#REPAIRABLE
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface Repairable {
++
++ @Contract(value = "_ -> new", pure = true)
++ static Repairable repairable(final RegistryKeySet types) {
++ return ItemComponentTypesBridge.bridge().repairable(types);
++ }
++
++ /**
++ * The types that this item is repairable to.
++ *
++ * @return item
++ */
++ @Contract(value = "-> new", pure = true)
++ RegistryKeySet types();
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ResolvableProfile.java b/src/main/java/io/papermc/paper/datacomponent/item/ResolvableProfile.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..c9fa347f068e2b7b90d1024ea554b2bf3cff3080
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ResolvableProfile.java
+@@ -0,0 +1,95 @@
++package io.papermc.paper.datacomponent.item;
++
++import com.destroystokyo.paper.profile.PlayerProfile;
++import com.destroystokyo.paper.profile.ProfileProperty;
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import java.util.Collection;
++import java.util.UUID;
++import java.util.concurrent.CompletableFuture;
++import org.intellij.lang.annotations.Pattern;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++import org.jspecify.annotations.Nullable;
++
++/**
++ * Holds player profile data that can be resolved to a {@link PlayerProfile}.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#PROFILE
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ResolvableProfile {
++
++ @Contract(value = "_ -> new", pure = true)
++ static ResolvableProfile resolvableProfile(final PlayerProfile profile) {
++ return ItemComponentTypesBridge.bridge().resolvableProfile(profile);
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static ResolvableProfile.Builder resolvableProfile() {
++ return ItemComponentTypesBridge.bridge().resolvableProfile();
++ }
++
++ @Contract(pure = true)
++ @Nullable UUID uuid();
++
++ @Contract(pure = true)
++ @Nullable String name();
++
++ @Contract(pure = true)
++ @Unmodifiable Collection properties();
++
++ @Contract(pure = true)
++ CompletableFuture resolve();
++
++ /**
++ * Builder for {@link ResolvableProfile}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets the name for this profile. Must be 16-or-less
++ * characters and not contain invalid characters.
++ *
++ * @param name the name
++ * @return the builder for chaining
++ * @see #name()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder name(@Pattern("^[!-~]{0,16}$") @Nullable String name);
++
++ /**
++ * Sets the UUID for this profile.
++ *
++ * @param uuid the UUID
++ * @return the builder for chaining
++ * @see #uuid()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder uuid(@Nullable UUID uuid);
++
++ /**
++ * Adds a property to this profile.
++ *
++ * @param property the property
++ * @return the builder for chaining
++ * @see #properties()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addProperty(ProfileProperty property);
++
++ /**
++ * Adds properties to this profile.
++ *
++ * @param properties the properties
++ * @return the builder for chaining
++ * @see #properties()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addProperties(Collection properties);
++ }
++}
+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..f79af65e8f3f8ffbb9be1cf1c6b537cd1e2b1031
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/SeededContainerLoot.java
+@@ -0,0 +1,71 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import net.kyori.adventure.key.Key;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the loot table and seed for a container.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#CONTAINER_LOOT
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface SeededContainerLoot {
++
++ @Contract(value = "_, _ -> new", pure = true)
++ static SeededContainerLoot seededContainerLoot(final Key lootTableKey, final long seed) {
++ return SeededContainerLoot.seededContainerLoot(lootTableKey).seed(seed).build();
++ }
++
++ @Contract(value = "_ -> new", pure = true)
++ static SeededContainerLoot.Builder seededContainerLoot(final Key lootTableKey) {
++ return ItemComponentTypesBridge.bridge().seededContainerLoot(lootTableKey);
++ }
++
++ /**
++ * Gets the loot table key.
++ *
++ * @return the loot table key
++ */
++ @Contract(pure = true)
++ Key lootTable();
++
++ /**
++ * Gets the loot table seed.
++ *
++ * @return the seed
++ */
++ @Contract(pure = true)
++ long seed();
++
++ /**
++ * Builder for {@link SeededContainerLoot}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets the loot table key.
++ *
++ * @param key the loot table key
++ * @return the builder for chaining
++ * @see #lootTable()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder lootTable(Key key);
++
++ /**
++ * Sets the loot table seed.
++ *
++ * @param seed the seed
++ * @return the builder for chaining
++ * @see #seed()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder seed(long seed);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/ShownInTooltip.java b/src/main/java/io/papermc/paper/datacomponent/item/ShownInTooltip.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..7e058aebcbd768517f6db51540598721cdae4425
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/ShownInTooltip.java
+@@ -0,0 +1,52 @@
++package io.papermc.paper.datacomponent.item;
++
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the state of whether a data component should be shown
++ * in an item's tooltip.
++ * @param the data component type
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ShownInTooltip {
++
++ /**
++ * Gets if the data component should be shown in the item's tooltip.
++ *
++ * @return {@code true} to show in the tooltip
++ */
++ @Contract(pure = true)
++ boolean showInTooltip();
++
++ /**
++ * Returns a copy of this data component with the specified
++ * show-in-tooltip state.
++ * @param showInTooltip {@code true} to show in the tooltip
++ * @return the new data component
++ */
++ @Contract(value = "_ -> new", pure = true)
++ T showInTooltip(boolean showInTooltip);
++
++ /**
++ * A builder for creating a {@link ShownInTooltip} data component.
++ * @param builder type
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder {
++
++ /**
++ * Sets if the data component should be shown in the item's tooltip.
++ *
++ * @param showInTooltip {@code true} to show in the tooltip
++ * @return the builder for chaining
++ * @see #showInTooltip()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ B showInTooltip(boolean showInTooltip);
++ }
++}
+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..f834512224fb8eb523442e9faa9c9aa2221df9f0
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/SuspiciousStewEffects.java
+@@ -0,0 +1,72 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import io.papermc.paper.potion.SuspiciousEffectEntry;
++import java.util.Arrays;
++import java.util.Collection;
++import java.util.List;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the effects that will be applied when consuming Suspicious Stew.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#SUSPICIOUS_STEW_EFFECTS
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface SuspiciousStewEffects {
++
++ @Contract(value = "_ -> new", pure = true)
++ static SuspiciousStewEffects suspiciousStewEffects(final SuspiciousEffectEntry ...effects) {
++ return suspiciousStewEffects(Arrays.asList(effects));
++ }
++
++ @Contract(value = "_ -> new", pure = true)
++ static SuspiciousStewEffects suspiciousStewEffects(final Collection effects) {
++ return suspiciousStewEffects().addAll(effects).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static SuspiciousStewEffects.Builder suspiciousStewEffects() {
++ return ItemComponentTypesBridge.bridge().suspiciousStewEffects();
++ }
++
++ /**
++ * Effects that will be applied when consuming Suspicious Stew.
++ *
++ * @return effects
++ */
++ @Contract(pure = true)
++ @Unmodifiable List effects();
++
++ /**
++ * Builder for {@link SuspiciousStewEffects}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Adds an effect applied to this builder.
++ *
++ * @param entry effect
++ * @return the builder for chaining
++ * @see #effects()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder add(SuspiciousEffectEntry entry);
++
++ /**
++ * Adds effects applied to this builder.
++ *
++ * @param entries effect
++ * @return the builder for chaining
++ * @see #effects()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addAll(Collection entries);
++ }
++}
+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..4dfa518a2038df3ba4fa628f37eaf23414a66e6b
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/Tool.java
+@@ -0,0 +1,145 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import io.papermc.paper.registry.set.RegistryKeySet;
++import java.util.Collection;
++import java.util.List;
++import net.kyori.adventure.util.TriState;
++import org.bukkit.block.BlockType;
++import org.checkerframework.checker.index.qual.NonNegative;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++import org.jspecify.annotations.Nullable;
++
++/**
++ * Controls the behavior of the item as a tool.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#TOOL
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface Tool {
++
++ @Contract(value = "-> new", pure = true)
++ static Tool.Builder tool() {
++ return ItemComponentTypesBridge.bridge().tool();
++ }
++
++ /**
++ * Mining speed to use if no rules match and don't override mining speed.
++ *
++ * @return default mining speed
++ */
++ @Contract(pure = true)
++ float defaultMiningSpeed();
++
++ /**
++ * Amount of durability to remove each time a block is mined with this tool.
++ *
++ * @return durability
++ */
++ @Contract(pure = true)
++ @NonNegative int damagePerBlock();
++
++ /**
++ * List of rule entries.
++ *
++ * @return rules
++ */
++ @Contract(pure = true)
++ @Unmodifiable List rules();
++
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Rule {
++
++ static Rule rule(final RegistryKeySet blocks, final @Nullable Float speed, final TriState correctForDrops) {
++ return ItemComponentTypesBridge.bridge().rule(blocks, speed, correctForDrops);
++ }
++
++ static Rule minesAndDrops(final RegistryKeySet blocks, final float speed) {
++ return rule(blocks, speed, TriState.TRUE);
++ }
++
++ static Rule deniesDrops(final RegistryKeySet blocks) {
++ return rule(blocks, null, TriState.FALSE);
++ }
++
++ static Rule overrideSpeed(final RegistryKeySet blocks, final float speed) {
++ return rule(blocks, speed, TriState.NOT_SET);
++ }
++
++ /**
++ * Blocks to match.
++ *
++ * @return blocks
++ */
++ RegistryKeySet blocks();
++
++ /**
++ * Overrides the mining speed if present and matched.
++ *
++ * {@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 a tri-state
++ */
++ TriState correctForDrops();
++ }
++
++ /**
++ * Builder for {@link Tool}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Controls the amount of durability to remove each time a block is mined with this tool.
++ *
++ * @param damage durability to remove
++ * @return the builder for chaining
++ * @see #damagePerBlock()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder damagePerBlock(@NonNegative int damage);
++
++ /**
++ * Controls mining speed to use if no rules match and don't override mining speed.
++ *
++ * @param miningSpeed mining speed
++ * @return the builder for chaining
++ * @see #defaultMiningSpeed()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder defaultMiningSpeed(float miningSpeed);
++
++ /**
++ * Adds a rule to the tool that controls the breaking speed / damage per block if matched.
++ *
++ * @param rule rule
++ * @return the builder for chaining
++ * @see #rules()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addRule(Rule rule);
++
++ /**
++ * Adds rules to the tool that control the breaking speed / damage per block if matched.
++ *
++ * @param rules rules
++ * @return the builder for chaining
++ * @see #rules()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addRules(Collection rules);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/Unbreakable.java b/src/main/java/io/papermc/paper/datacomponent/item/Unbreakable.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..498eb479dce406d2b0b470b327eac8279a0d98bc
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/Unbreakable.java
+@@ -0,0 +1,34 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * If set, the item will not lose any durability when used.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#UNBREAKABLE
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface Unbreakable extends ShownInTooltip {
++
++ @Contract(value = "_ -> new", pure = true)
++ static Unbreakable unbreakable(final boolean showInTooltip) {
++ return unbreakable().showInTooltip(showInTooltip).build();
++ }
++
++ @Contract(value = "-> new", pure = true)
++ static Unbreakable.Builder unbreakable() {
++ return ItemComponentTypesBridge.bridge().unbreakable();
++ }
++
++ /**
++ * Builder for {@link Unbreakable}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends ShownInTooltip.Builder, DataComponentBuilder {
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/UseCooldown.java b/src/main/java/io/papermc/paper/datacomponent/item/UseCooldown.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..5840f12286aedfb89d3fc4882508e11a706f5f6b
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/UseCooldown.java
+@@ -0,0 +1,66 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import net.kyori.adventure.key.Key;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++import org.jspecify.annotations.Nullable;
++
++/**
++ * Holds the contents of cooldown information when an item is used.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#USE_COOLDOWN
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface UseCooldown {
++
++ /**
++ * Creates a new builder for use cooldown.
++ *
++ * @param seconds the duration in seconds; must be positive
++ * @return builder
++ */
++ @Contract(value = "_ -> new", pure = true)
++ static UseCooldown.Builder useCooldown(final float seconds) {
++ return ItemComponentTypesBridge.bridge().useCooldown(seconds);
++ }
++
++ /**
++ * The amount of seconds the cooldown will be active for.
++ *
++ * @return cooldown seconds
++ */
++ @Contract(pure = true)
++ float seconds();
++
++ /**
++ * The unique resource location to identify this cooldown group.
++ *
++ * This allows items to share cooldowns with other items in the same cooldown group, if present.
++ *
++ * @return cooldown group, or null if not present
++ */
++ @Contract(pure = true)
++ @Nullable
++ Key cooldownGroup();
++
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets a unique resource location for this cooldown group.
++ *
++ * This allows items to share cooldowns with other items in the same cooldown group.
++ *
++ *
++ * @param key the unique resource location; can be null
++ * @return the builder for chaining
++ * @see #cooldownGroup()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder cooldownGroup(@Nullable Key key);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/UseRemainder.java b/src/main/java/io/papermc/paper/datacomponent/item/UseRemainder.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..31343f5068b3ca60bc237323063a012faa0141b7
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/UseRemainder.java
+@@ -0,0 +1,48 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import org.bukkit.inventory.ItemStack;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the contents of item transformation information when an item is used.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#USE_REMAINDER
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface UseRemainder {
++
++ @Contract(value = "_ -> new", pure = true)
++ static UseRemainder useRemainder(final ItemStack itemStack) {
++ return ItemComponentTypesBridge.bridge().useRemainder(itemStack);
++ }
++
++ /**
++ * The item that the item that is consumed is transformed into.
++ *
++ * @return item
++ */
++ @Contract(value = "-> new", pure = true)
++ ItemStack transformInto();
++
++ /**
++ * Builder for {@link UseRemainder}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends ShownInTooltip.Builder, DataComponentBuilder {
++
++ /**
++ * Sets the transform item of this builder.
++ *
++ * @param itemStack item
++ * @return the builder for chaining
++ * @see #transformInto()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder transformInto(ItemStack itemStack);
++ }
++}
+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..30a02149a02042316885b92e39e7ab6c5abbabf2
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/WritableBookContent.java
+@@ -0,0 +1,81 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import io.papermc.paper.util.Filtered;
++import java.util.Collection;
++import java.util.List;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the pages for a writable book.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#WRITABLE_BOOK_CONTENT
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface WritableBookContent {
++
++ @Contract(value = "-> new", pure = true)
++ static WritableBookContent.Builder writeableBookContent() {
++ return ItemComponentTypesBridge.bridge().writeableBookContent();
++ }
++
++ /**
++ * Holds the pages that can be written to for this component.
++ *
++ * @return pages, as filtered objects
++ */
++ @Contract(pure = true)
++ @Unmodifiable List> pages();
++
++ /**
++ * Builder for {@link WritableBookContent}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Adds a page that can be written to for this builder.
++ *
++ * @param page page
++ * @return the builder for chaining
++ * @see #pages()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addPage(String page);
++
++ /**
++ * Adds pages that can be written to for this builder.
++ *
++ * @param pages pages
++ * @return the builder for chaining
++ * @see #pages()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addPages(Collection pages);
++
++ /**
++ * Adds a filterable page that can be written to for this builder.
++ *
++ * @param page page
++ * @return the builder for chaining
++ * @see #pages()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addFilteredPage(Filtered page);
++
++ /**
++ * Adds filterable pages that can be written to for this builder.
++ *
++ * @param pages pages
++ * @return the builder for chaining
++ * @see #pages()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addFilteredPages(Collection> pages);
++ }
++}
+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..86915d2c1435d4a5df2bce0318bdf169d03f28ec
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/WrittenBookContent.java
+@@ -0,0 +1,173 @@
++package io.papermc.paper.datacomponent.item;
++
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import io.papermc.paper.util.Filtered;
++import java.util.Collection;
++import java.util.List;
++import net.kyori.adventure.text.Component;
++import net.kyori.adventure.text.ComponentLike;
++import org.checkerframework.common.value.qual.IntRange;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.Unmodifiable;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Holds the contents and metadata of a Written Book.
++ * @see io.papermc.paper.datacomponent.DataComponentTypes#WRITTEN_BOOK_CONTENT
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface WrittenBookContent {
++
++ @Contract(value = "_, _ -> new", pure = true)
++ static WrittenBookContent.Builder writtenBookContent(final String title, final String author) {
++ return writtenBookContent(Filtered.of(title, null), author);
++ }
++
++ @Contract(value = "_, _ -> new", pure = true)
++ static WrittenBookContent.Builder writtenBookContent(final Filtered title, final String author) {
++ return ItemComponentTypesBridge.bridge().writtenBookContent(title, author);
++ }
++
++ /**
++ * Title of this book.
++ *
++ * @return title
++ */
++ @Contract(pure = true)
++ Filtered title();
++
++ /**
++ * Player name of the author of this book.
++ *
++ * @return author
++ */
++ @Contract(pure = true)
++ String author();
++
++ /**
++ * The number of times this book has been copied (0 = original).
++ *
++ * @return generation
++ */
++ @Contract(pure = true)
++ @IntRange(from = 0, to = 3) int generation();
++
++ /**
++ * Gets the pages of this book.
++ *
++ * @return pages
++ */
++ @Contract(pure = true)
++ @Unmodifiable List> pages();
++
++ /**
++ * If the chat components in this book have already been resolved (entity selectors, scores substituted).
++ * If {@code false}, will be resolved when opened by a player.
++ *
++ * @return resolved
++ */
++ @Contract(pure = true)
++ boolean resolved();
++
++ /**
++ * Builder for {@link WrittenBookContent}.
++ */
++ @ApiStatus.Experimental
++ @ApiStatus.NonExtendable
++ interface Builder extends DataComponentBuilder {
++
++ /**
++ * Sets the title of this book.
++ *
++ * @param title the title
++ * @return the builder for chaining
++ * @see #title()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder title(String title);
++
++ /**
++ * Sets the filterable title of this book.
++ *
++ * @param title the title
++ * @return the builder for chaining
++ * @see #title()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder filteredTitle(Filtered title);
++
++ /**
++ * Sets the author of this book.
++ *
++ * @param author the author
++ * @return the builder for chaining
++ * @see #author()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder author(String author);
++
++ /**
++ * Sets the generation of this book.
++ *
++ * @param generation the generation, [0-3]
++ * @return the builder for chaining
++ * @see #generation()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder generation(@IntRange(from = 0, to = 3) int generation);
++
++ /**
++ * Sets if the chat components in this book have already been resolved (entity selectors, scores substituted).
++ * If {@code false}, will be resolved when opened by a player.
++ *
++ * @param resolved resolved
++ * @return the builder for chaining
++ * @see #resolved()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder resolved(boolean resolved);
++
++ /**
++ * Adds a page to this book.
++ *
++ * @param page the page
++ * @return the builder for chaining
++ * @see #pages()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addPage(ComponentLike page);
++
++ /**
++ * Adds pages to this book.
++ *
++ * @param page the pages
++ * @return the builder for chaining
++ * @see #pages()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addPages(Collection extends ComponentLike> page);
++
++ /**
++ * Adds a filterable page to this book.
++ *
++ * @param page the page
++ * @return the builder for chaining
++ * @see #pages()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addFilteredPage(Filtered extends ComponentLike> page);
++
++ /**
++ * Adds filterable pages to this book.
++ *
++ * @param pages the pages
++ * @return the builder for chaining
++ * @see #pages()
++ */
++ @Contract(value = "_ -> this", mutates = "this")
++ Builder addFilteredPages(Collection> pages);
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/consumable/ApplyStatusEffectsConsumeEffect.java b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ApplyStatusEffectsConsumeEffect.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..0dac27dc6002b599deed7fb779de86f96907a942
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ApplyStatusEffectsConsumeEffect.java
+@@ -0,0 +1,42 @@
++package io.papermc.paper.datacomponent.item.consumable;
++
++import java.util.List;
++import org.bukkit.potion.PotionEffect;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Represents a consumable effect that applies effects based on a probability on consumption.
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ApplyStatusEffectsConsumeEffect extends ConsumeEffect {
++
++ /**
++ * Creates a consume effect that gives status effects on consumption.
++ *
++ * @param effects the potion effects to apply
++ * @param probability the probability of these effects being applied, between 0 and 1 inclusive.
++ * @return the effect
++ */
++ @Contract(value = "_, _ -> new", pure = true)
++ static ApplyStatusEffectsConsumeEffect applyStatusEffects(final List effects, final float probability) {
++ return ConsumableTypesBridge.bridge().applyStatusEffects(effects, probability);
++ }
++
++ /**
++ * Effect instances to grant
++ *
++ * @return effect
++ */
++ List effects();
++
++ /**
++ * Float between 0 and 1, chance for the effect to be applied.
++ *
++ * @return chance
++ */
++ float probability();
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/consumable/ClearAllStatusEffectsConsumeEffect.java b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ClearAllStatusEffectsConsumeEffect.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..d6399bc32c5c330dc9969bdfc8f98f43bcbaf2d4
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ClearAllStatusEffectsConsumeEffect.java
+@@ -0,0 +1,21 @@
++package io.papermc.paper.datacomponent.item.consumable;
++
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Represents a consumable effect that clears all effects on consumption.
++ */
++@NullMarked
++public interface ClearAllStatusEffectsConsumeEffect extends ConsumeEffect {
++
++ /**
++ * Creates a consume effect that clears all status effects.
++ *
++ * @return effect instance
++ */
++ @Contract(value = "-> new", pure = true)
++ static ClearAllStatusEffectsConsumeEffect clearAllStatusEffects() {
++ return ConsumableTypesBridge.bridge().clearAllStatusEffects();
++ }
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/consumable/ConsumableTypesBridge.java b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ConsumableTypesBridge.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..85cb8c4ebc7b372842f8a262790f3c5dcb86f161
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ConsumableTypesBridge.java
+@@ -0,0 +1,32 @@
++package io.papermc.paper.datacomponent.item.consumable;
++
++import io.papermc.paper.registry.set.RegistryKeySet;
++import java.util.List;
++import java.util.Optional;
++import java.util.ServiceLoader;
++import net.kyori.adventure.key.Key;
++import org.bukkit.potion.PotionEffect;
++import org.bukkit.potion.PotionEffectType;
++import org.jetbrains.annotations.ApiStatus;
++import org.jspecify.annotations.NullMarked;
++
++@NullMarked
++@ApiStatus.Internal
++interface ConsumableTypesBridge {
++
++ Optional BRIDGE = ServiceLoader.load(ConsumableTypesBridge.class).findFirst();
++
++ static ConsumableTypesBridge bridge() {
++ return BRIDGE.orElseThrow();
++ }
++
++ ApplyStatusEffectsConsumeEffect applyStatusEffects(List effectList, float probability);
++
++ RemoveStatusEffectsConsumeEffect removeStatusEffects(RegistryKeySet potionEffectTypeTagKey);
++
++ ClearAllStatusEffectsConsumeEffect clearAllStatusEffects();
++
++ PlaySoundConsumeEffect playSoundEffect(Key sound);
++
++ TeleportRandomlyConsumeEffect teleportRandomlyEffect(float diameter);
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/consumable/ConsumeEffect.java b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ConsumeEffect.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..c5889c75c421ff10e51faf3fd769a38dc1287152
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ConsumeEffect.java
+@@ -0,0 +1,14 @@
++package io.papermc.paper.datacomponent.item.consumable;
++
++import org.jetbrains.annotations.ApiStatus;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Effect that occurs when consuming an item.
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface ConsumeEffect {
++
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/consumable/ItemUseAnimation.java b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ItemUseAnimation.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..8cd6dbe4ea5ee3270b9428a9c29cbd88823d9f6c
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/consumable/ItemUseAnimation.java
+@@ -0,0 +1,17 @@
++package io.papermc.paper.datacomponent.item.consumable;
++
++/**
++ * Represents the hand animation that is used when a player is consuming this item.
++ */
++public enum ItemUseAnimation {
++ NONE,
++ EAT,
++ DRINK,
++ BLOCK,
++ BOW,
++ SPEAR,
++ CROSSBOW,
++ SPYGLASS,
++ TOOT_HORN,
++ BRUSH
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/consumable/PlaySoundConsumeEffect.java b/src/main/java/io/papermc/paper/datacomponent/item/consumable/PlaySoundConsumeEffect.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..aca3a7d5f78385b34ffe39c2e293b23d2fc138b5
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/consumable/PlaySoundConsumeEffect.java
+@@ -0,0 +1,33 @@
++package io.papermc.paper.datacomponent.item.consumable;
++
++import net.kyori.adventure.key.Key;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Represents a consumable effect that plays a sound on consumption.
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface PlaySoundConsumeEffect extends ConsumeEffect {
++
++ /**
++ * Creates a consume effect that plays a sound on consumption.
++ *
++ * @param key the sound effect to play
++ * @return the effect
++ */
++ @Contract(value = "_ -> new", pure = true)
++ static PlaySoundConsumeEffect playSoundConsumeEffect(final Key key) {
++ return ConsumableTypesBridge.bridge().playSoundEffect(key);
++ }
++
++ /**
++ * Sound effect to play in the world
++ *
++ * @return sound effect
++ */
++ Key sound();
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/consumable/RemoveStatusEffectsConsumeEffect.java b/src/main/java/io/papermc/paper/datacomponent/item/consumable/RemoveStatusEffectsConsumeEffect.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..70b406a124dfb16a7354dab457f5bd5dc8f36832
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/consumable/RemoveStatusEffectsConsumeEffect.java
+@@ -0,0 +1,34 @@
++package io.papermc.paper.datacomponent.item.consumable;
++
++import io.papermc.paper.registry.set.RegistryKeySet;
++import org.bukkit.potion.PotionEffectType;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++/**
++ * Represents a consumable effect that removes status effects on consumption
++ */
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface RemoveStatusEffectsConsumeEffect extends ConsumeEffect {
++
++ /**
++ * Creates a consume effect that gives status effects on consumption.
++ *
++ * @param key the sound effect to play
++ * @return the effect
++ */
++ @Contract(value = "_ -> new", pure = true)
++ static RemoveStatusEffectsConsumeEffect removeEffects(final RegistryKeySet key) {
++ return ConsumableTypesBridge.bridge().removeStatusEffects(key);
++ }
++
++ /**
++ * Potion effects to remove
++ *
++ * @return effects
++ */
++ RegistryKeySet removeEffects();
++}
+diff --git a/src/main/java/io/papermc/paper/datacomponent/item/consumable/TeleportRandomlyConsumeEffect.java b/src/main/java/io/papermc/paper/datacomponent/item/consumable/TeleportRandomlyConsumeEffect.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..f0751babbaaaedb188c109589aff1a65cde3bec1
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/datacomponent/item/consumable/TeleportRandomlyConsumeEffect.java
+@@ -0,0 +1,29 @@
++package io.papermc.paper.datacomponent.item.consumable;
++
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++import org.jspecify.annotations.NullMarked;
++
++@NullMarked
++@ApiStatus.Experimental
++@ApiStatus.NonExtendable
++public interface TeleportRandomlyConsumeEffect extends ConsumeEffect {
++
++ /**
++ * Creates a consume effect that randomly teleports the entity on consumption.
++ *
++ * @param diameter diameter of random teleportation
++ * @return the effect
++ */
++ @Contract(value = "_ -> new", pure = true)
++ static TeleportRandomlyConsumeEffect teleportRandomlyEffect(final float diameter) {
++ return ConsumableTypesBridge.bridge().teleportRandomlyEffect(diameter);
++ }
++
++ /**
++ * The max range that the entity can be teleported to.
++ *
++ * @return teleportation diameter
++ */
++ float diameter();
++}
+diff --git a/src/main/java/io/papermc/paper/item/MapPostProcessing.java b/src/main/java/io/papermc/paper/item/MapPostProcessing.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..5843768d0be2ae4a0219636ed7640727808da567
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/item/MapPostProcessing.java
+@@ -0,0 +1,6 @@
++package io.papermc.paper.item;
++
++public enum MapPostProcessing {
++ LOCK,
++ SCALE
++}
+diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java
+index 9b39e33514b15a9d07104e2ad826d0da11f569d6..116857b4479565b602b94d227ee32dc29ebd6e5f 100644
+--- a/src/main/java/io/papermc/paper/registry/RegistryKey.java
++++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
+@@ -1,5 +1,6 @@
+ package io.papermc.paper.registry;
+
++import io.papermc.paper.datacomponent.DataComponentType;
+ import net.kyori.adventure.key.Keyed;
+ import org.bukkit.Art;
+ import org.bukkit.Fluid;
+@@ -124,6 +125,11 @@ public sealed interface RegistryKey extends Keyed permits RegistryKeyImpl {
+ * @see io.papermc.paper.registry.keys.SoundEventKeys
+ */
+ RegistryKey SOUND_EVENT = create("sound_event");
++ /**
++ * Built-in registry for data component types.
++ * @see io.papermc.paper.registry.keys.DataComponentTypeKeys
++ */
++ RegistryKey DATA_COMPONENT_TYPE = create("data_component_type");
+
+
+
+diff --git a/src/main/java/io/papermc/paper/util/Filtered.java b/src/main/java/io/papermc/paper/util/Filtered.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..6919f01a18bc0ab375d2e0541206524304243d19
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/util/Filtered.java
+@@ -0,0 +1,30 @@
++package io.papermc.paper.util;
++
++import org.checkerframework.checker.nullness.qual.NonNull;
++import org.checkerframework.checker.nullness.qual.Nullable;
++import org.jetbrains.annotations.ApiStatus;
++import org.jetbrains.annotations.Contract;
++
++/**
++ * Denotes that this type is filterable by the client, and may be shown differently
++ * depending on the player's set configuration.
++ *
++ * @param type of value
++ */
++@ApiStatus.Experimental
++public interface Filtered {
++
++ @Contract(value = "_, _ -> new", pure = true)
++ static @NonNull Filtered of(final @NonNull T raw, final @Nullable T filtered) {
++ @ApiStatus.Internal
++ record Instance(T raw, T filtered) implements Filtered {}
++
++ return new Instance<>(raw, filtered);
++ }
++
++ @Contract(pure = true)
++ @NonNull T raw();
++
++ @Contract(pure = true)
++ @Nullable T filtered();
++}
+diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java
+index 615eb24ffdd8f6d55ccd4f21760b809c1098bc68..1b3e120bb9b10b65eb6225af8f08caed5973007d 100644
+--- a/src/main/java/org/bukkit/Material.java
++++ b/src/main/java/org/bukkit/Material.java
+@@ -137,7 +137,7 @@ import org.jetbrains.annotations.Nullable;
+ @SuppressWarnings({"DeprecatedIsStillUsed", "deprecation"}) // Paper
+ public enum Material implements Keyed, Translatable, net.kyori.adventure.translation.Translatable { // Paper
+ //
+- AIR(9648, 0),
++ AIR(9648, 64), // Paper - air technically stacks to 64
+ STONE(22948),
+ GRANITE(21091),
+ POLISHED_GRANITE(5477),
+@@ -5784,6 +5784,7 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+ */
+ @ApiStatus.Internal
+ @Nullable
++ @org.jetbrains.annotations.Contract(pure = true) // Paper
+ public ItemType asItemType() {
+ return itemType.get();
+ }
+@@ -5796,7 +5797,47 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+ */
+ @ApiStatus.Internal
+ @Nullable
++ @org.jetbrains.annotations.Contract(pure = true) // Paper
+ public BlockType asBlockType() {
+ return blockType.get();
+ }
++
++ // Paper start - data component API
++ /**
++ * Gets the default value of the data component type for this item type.
++ *
++ * @param type the data component type
++ * @param the value type
++ * @return the default value or {@code null} if there is none
++ * @see #hasDefaultData(io.papermc.paper.datacomponent.DataComponentType) for DataComponentType.NonValued
++ * @throws IllegalArgumentException if {@link #isItem()} is {@code false}
++ */
++ public @Nullable T getDefaultData(final io.papermc.paper.datacomponent.DataComponentType.@NotNull Valued type) {
++ Preconditions.checkArgument(this.asItemType() != null);
++ return this.asItemType().getDefaultData(type);
++ }
++
++ /**
++ * Checks if the data component type has a default value for this item type.
++ *
++ * @param type the data component type
++ * @return {@code true} if there is a default value
++ * @throws IllegalArgumentException if {@link #isItem()} is {@code false}
++ */
++ public boolean hasDefaultData(final io.papermc.paper.datacomponent.@NotNull DataComponentType type) {
++ Preconditions.checkArgument(this.asItemType() != null);
++ return this.asItemType().hasDefaultData(type);
++ }
++
++ /**
++ * Gets the default data component types for this item type.
++ *
++ * @return an immutable set of data component types
++ * @throws IllegalArgumentException if {@link #isItem()} is {@code false}
++ */
++ public java.util.@org.jetbrains.annotations.Unmodifiable @NotNull Set getDefaultDataTypes() {
++ Preconditions.checkArgument(this.asItemType() != null);
++ return this.asItemType().getDefaultDataTypes();
++ }
++ // Paper end - data component API
+ }
+diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java
+index 7cf7c6d05aa6cbf3f0c8612831404552c6a7b84a..c60e31425efd7b863941f5538faef6c0552290ae 100644
+--- a/src/main/java/org/bukkit/Registry.java
++++ b/src/main/java/org/bukkit/Registry.java
+@@ -376,6 +376,7 @@ public interface Registry extends Iterable {
+ */
+ Registry POTION_EFFECT_TYPE = EFFECT;
+ // Paper end - potion effect type registry
++ Registry DATA_COMPONENT_TYPE = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.DATA_COMPONENT_TYPE); // Paper
+ /**
+ * Get the object by its key.
+ *
+diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
+index b59222b8c262545d100a9fd28b3bf1d2a4cf4eb0..8071624df30b36e2f96dcf7a0b2ada20179b1641 100644
+--- a/src/main/java/org/bukkit/inventory/ItemStack.java
++++ b/src/main/java/org/bukkit/inventory/ItemStack.java
+@@ -1,10 +1,11 @@
+ package org.bukkit.inventory;
+
+ import com.google.common.base.Preconditions;
+-import com.google.common.collect.ImmutableMap;
+ import java.util.LinkedHashMap;
+ import java.util.Locale;
+ import java.util.Map;
++import io.papermc.paper.datacomponent.DataComponentBuilder;
++import io.papermc.paper.datacomponent.DataComponentType;
+ import org.bukkit.Bukkit;
+ import org.bukkit.Material;
+ import org.bukkit.NamespacedKey;
+@@ -1137,4 +1138,173 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
+ return Bukkit.getUnsafe().computeTooltipLines(this, tooltipContext, player);
+ }
+ // Paper end - expose itemstack tooltip lines
++
++ // Paper start - data component API
++ /**
++ * Gets the value for the data component type on this stack.
++ *
++ * @param type the data component type
++ * @param the value type
++ * @return the value for the data component type, or {@code null} if not set or marked as removed
++ * @see #hasData(io.papermc.paper.datacomponent.DataComponentType) for DataComponentType.NonValued
++ */
++ @org.jetbrains.annotations.Contract(pure = true)
++ public @Nullable T getData(final io.papermc.paper.datacomponent.DataComponentType.@NotNull Valued type) {
++ return this.craftDelegate.getData(type);
++ }
++
++ /**
++ * Gets the value for the data component type on this stack with
++ * a fallback value.
++ *
++ * @param type the data component type
++ * @param fallback the fallback value if the value isn't present
++ * @param the value type
++ * @return the value for the data component type or the fallback value
++ */
++ @Utility
++ @org.jetbrains.annotations.Contract(value = "_, !null -> !null", pure = true)
++ public @Nullable T getDataOrDefault(final io.papermc.paper.datacomponent.DataComponentType.@NotNull Valued extends T> type, final @Nullable T fallback) {
++ final T object = this.getData(type);
++ return object != null ? object : fallback;
++ }
++
++ /**
++ * Checks if the data component type is set on the itemstack.
++ *
++ * @param type the data component type
++ * @return {@code true} if set, {@code false} otherwise
++ */
++ @org.jetbrains.annotations.Contract(pure = true)
++ public boolean hasData(final io.papermc.paper.datacomponent.@NotNull DataComponentType type) {
++ return this.craftDelegate.hasData(type);
++ }
++
++ /**
++ * Gets all the data component types set on this stack.
++ *
++ * @return an immutable set of data component types
++ */
++ @org.jetbrains.annotations.Contract("-> new")
++ public java.util.@org.jetbrains.annotations.Unmodifiable Set getDataTypes() {
++ return this.craftDelegate.getDataTypes();
++ }
++
++ /**
++ * Sets the value of the data component type for this itemstack. To
++ * reset the value to the default for the {@link #getType() item type}, use
++ * {@link #resetData(io.papermc.paper.datacomponent.DataComponentType)}. To mark the data component type
++ * as removed, use {@link #unsetData(io.papermc.paper.datacomponent.DataComponentType)}.
++ *
++ * @param type the data component type
++ * @param valueBuilder value builder
++ * @param value type
++ */
++ @Utility
++ public void setData(final io.papermc.paper.datacomponent.DataComponentType.@NotNull Valued type, final @NotNull DataComponentBuilder valueBuilder) {
++ this.setData(type, valueBuilder.build());
++ }
++
++ /**
++ * Modifies the value of the specified data component type for this item stack based on the result
++ * of applying a given function to the current value.
++ *
++ * If the function returns {@code null}, the data component type will be reset using
++ * {@link #unsetData(DataComponentType)}. Otherwise, the
++ * component value will be updated with the new result using {@link #setData(DataComponentType.Valued, Object)}.
++ *
++ * @param the type of the data component's value
++ * @param type the data component type to be modified
++ * @param consumer a function that takes the current component value (can be {@code null}) and
++ * returns the modified value (or {@code null} to unset)
++ */
++ @Utility
++ public void editData(final io.papermc.paper.datacomponent.DataComponentType.@NotNull Valued type, final @NotNull java.util.function.Function<@Nullable T, @Nullable T> consumer) {
++ T value = getData(type);
++ T newType = consumer.apply(value);
++ if (newType == null) {
++ unsetData(type);
++ } else {
++ setData(type, newType);
++ }
++ }
++
++ /**
++ * Sets the value of the data component type for this itemstack. To
++ * reset the value to the default for the {@link #getType() item type}, use
++ * {@link #resetData(io.papermc.paper.datacomponent.DataComponentType)}. To mark the data component type
++ * as removed, use {@link #unsetData(io.papermc.paper.datacomponent.DataComponentType)}.
++ *
++ * @param type the data component type
++ * @param value value to set
++ * @param value type
++ */
++ public void setData(final io.papermc.paper.datacomponent.DataComponentType.@NotNull Valued type, final @NotNull T value) {
++ this.craftDelegate.setData(type, value);
++ }
++
++ /**
++ * Marks this non-valued data component type as present in this itemstack.
++ *
++ * @param type the data component type
++ */
++ public void setData(final io.papermc.paper.datacomponent.DataComponentType.@NotNull NonValued type) {
++ this.craftDelegate.setData(type);
++ }
++
++ /**
++ * Marks this data component as removed for this itemstack.
++ *
++ * @param type the data component type
++ */
++ public void unsetData(final io.papermc.paper.datacomponent.@NotNull DataComponentType type) {
++ this.craftDelegate.unsetData(type);
++ }
++
++ /**
++ * Resets the value of this component to be the default
++ * value for the item type from {@link Material#getDefaultData(io.papermc.paper.datacomponent.DataComponentType.Valued)}.
++ *
++ * @param type the data component type
++ */
++ public void resetData(final io.papermc.paper.datacomponent.@NotNull DataComponentType type) {
++ this.craftDelegate.resetData(type);
++ }
++
++ /**
++ * Checks if the data component type is overridden from the default for the
++ * item type.
++ *
++ * @param type the data component type
++ * @return {@code true} if the data type is overridden
++ */
++ public boolean isOverridden(final io.papermc.paper.datacomponent.@NotNull DataComponentType type) {
++ return this.craftDelegate.isOverridden(type);
++ }
++
++ /**
++ * Checks if this itemstack matches another given itemstack excluding the provided components.
++ * This is useful if you are wanting to ignore certain properties of itemstacks, such as durability.
++ *
++ * @param item the item to compare
++ * @param excludeTypes the data component types to ignore
++ * @return {@code true} if the provided item is equal, ignoring the provided components
++ */
++ public boolean matchesWithoutData(final @NotNull ItemStack item, final @NotNull io.papermc.paper.registry.set.RegistrySet excludeTypes) {
++ return this.matchesWithoutData(item, excludeTypes, false);
++ }
++
++ /**
++ * Checks if this itemstack matches another given itemstack excluding the provided components.
++ * This is useful if you are wanting to ignore certain properties of itemstacks, such as durability.
++ *
++ * @param item the item to compare
++ * @param excludeTypes the data component types to ignore
++ * @param ignoreCount ignore the count of the item
++ * @return {@code true} if the provided item is equal, ignoring the provided components
++ */
++ public boolean matchesWithoutData(final @NotNull ItemStack item, final @NotNull io.papermc.paper.registry.set.RegistrySet excludeTypes, final boolean ignoreCount) {
++ return this.craftDelegate.matchesWithoutData(item, excludeTypes, ignoreCount);
++ }
++ // Paper end - data component API
+ }
+diff --git a/src/main/java/org/bukkit/inventory/ItemType.java b/src/main/java/org/bukkit/inventory/ItemType.java
+index 72803c00e4af576f286d2af34bf300ee554a7f3c..9769726ec1e227606a79ccab1e8e439ef9ec16c1 100644
+--- a/src/main/java/org/bukkit/inventory/ItemType.java
++++ b/src/main/java/org/bukkit/inventory/ItemType.java
+@@ -2483,4 +2483,30 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
+ */
+ @Nullable ItemRarity getItemRarity();
+ // Paper end - expand ItemRarity API
++ // Paper start - data component API
++ /**
++ * Gets the default value of the data component type for this item type.
++ *
++ * @param type the data component type
++ * @param the value type
++ * @return the default value or {@code null} if there is none
++ * @see #hasDefaultData(io.papermc.paper.datacomponent.DataComponentType) for DataComponentType.NonValued
++ */
++ @Nullable T getDefaultData(io.papermc.paper.datacomponent.DataComponentType.@NotNull Valued type);
++
++ /**
++ * Checks if the data component type has a default value for this item type.
++ *
++ * @param type the data component type
++ * @return {@code true} if there is a default value
++ */
++ boolean hasDefaultData(io.papermc.paper.datacomponent.@NotNull DataComponentType type);
++
++ /**
++ * Gets the default data component types for this item type.
++ *
++ * @return an immutable set of data component types
++ */
++ java.util.@org.jetbrains.annotations.Unmodifiable @NotNull Set getDefaultDataTypes();
++ // Paper end - data component API
+ }
diff --git a/patches/api/0497-WIP-DataComponent-API.patch b/patches/api/0497-WIP-DataComponent-API.patch
deleted file mode 100644
index f7b16e5cee..0000000000
--- a/patches/api/0497-WIP-DataComponent-API.patch
+++ /dev/null
@@ -1,4245 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
-Date: Sun, 28 Apr 2024 19:53:06 -0400
-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..92ea82ee95c449916955631297a059f1b9198c9b
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/block/BlockPredicate.java
-@@ -0,0 +1,50 @@
-+package io.papermc.paper.block;
-+
-+import io.papermc.paper.registry.set.RegistryKeySet;
-+import org.bukkit.block.BlockType;
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jetbrains.annotations.Contract;
-+import org.jspecify.annotations.NullMarked;
-+import org.jspecify.annotations.Nullable;
-+
-+@NullMarked
-+@ApiStatus.Experimental
-+@ApiStatus.NonExtendable
-+public interface BlockPredicate {
-+
-+ static Builder predicate() {
-+ //
-+ record BlockPredicateImpl(@Nullable RegistryKeySet blocks) implements BlockPredicate {
-+ }
-+
-+ class BuilderImpl implements Builder {
-+
-+ private @Nullable RegistryKeySet blocks;
-+
-+ @Override
-+ public Builder blocks(final @Nullable RegistryKeySet blocks) {
-+ this.blocks = blocks;
-+ return this;
-+ }
-+
-+ @Override
-+ public BlockPredicate build() {
-+ return new BlockPredicateImpl(this.blocks);
-+ }
-+ }
-+ //
-+ return new BuilderImpl();
-+ }
-+
-+ @Nullable RegistryKeySet blocks();
-+
-+ @ApiStatus.Experimental
-+ @ApiStatus.NonExtendable
-+ interface Builder {
-+
-+ @Contract(value = "_ -> this", mutates = "this")
-+ Builder blocks(@Nullable RegistryKeySet blocks);
-+
-+ BlockPredicate build();
-+ }
-+}
-diff --git a/src/main/java/io/papermc/paper/datacomponent/BuildableDataComponent.java b/src/main/java/io/papermc/paper/datacomponent/BuildableDataComponent.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..4d2ee71b82ff4a66c7f84e73c028f146e0f851ad
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/datacomponent/BuildableDataComponent.java
-@@ -0,0 +1,19 @@
-+package io.papermc.paper.datacomponent;
-+
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jetbrains.annotations.Contract;
-+import org.jspecify.annotations.NullMarked;
-+
-+@NullMarked
-+@ApiStatus.Experimental
-+@ApiStatus.NonExtendable
-+public interface BuildableDataComponent, B extends DataComponentBuilder> {
-+
-+ /**
-+ * Creates a new builder from this data component.
-+ *
-+ * @return a new builder
-+ */
-+ @Contract(value = "-> new", pure = true)
-+ B toBuilder();
-+}
-diff --git a/src/main/java/io/papermc/paper/datacomponent/DataComponentBuilder.java b/src/main/java/io/papermc/paper/datacomponent/DataComponentBuilder.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..9365e57499c8e337a40835b2ec9a92ebe4391bfc
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/datacomponent/DataComponentBuilder.java
-@@ -0,0 +1,24 @@
-+package io.papermc.paper.datacomponent;
-+
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jetbrains.annotations.Contract;
-+import org.jspecify.annotations.NullMarked;
-+
-+/**
-+ * Base builder type for all component builders.
-+ *
-+ * @param built component type
-+ */
-+@NullMarked
-+@ApiStatus.Experimental
-+@ApiStatus.NonExtendable
-+public interface DataComponentBuilder {
-+
-+ /**
-+ * Builds the immutable component value.
-+ *
-+ * @return a new component value
-+ */
-+ @Contract(value = "-> new", pure = true)
-+ C build();
-+}
-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..e2266d86a4dd1bf20346e48c428f8baf8a84b76b
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/datacomponent/DataComponentType.java
-@@ -0,0 +1,30 @@
-+package io.papermc.paper.datacomponent;
-+
-+import org.bukkit.Keyed;
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jspecify.annotations.NullMarked;
-+
-+@NullMarked
-+@ApiStatus.Experimental
-+@ApiStatus.NonExtendable
-+public interface DataComponentType extends Keyed {
-+
-+ /**
-+ * Checks if this data component type is persistent, or
-+ * that it will be saved with any itemstack it's attached to.
-+ *
-+ * @return {@code true} if persistent, {@code false} otherwise
-+ */
-+ boolean isPersistent();
-+
-+ @SuppressWarnings("unused")
-+ @ApiStatus.NonExtendable
-+ interface Valued extends DataComponentType {
-+
-+ }
-+
-+ @ApiStatus.NonExtendable
-+ interface NonValued extends DataComponentType {
-+
-+ }
-+}
-diff --git a/src/main/java/io/papermc/paper/datacomponent/DataComponentTypes.java b/src/main/java/io/papermc/paper/datacomponent/DataComponentTypes.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..e79800d626fdde02be88c75fa13d4793e7af1168
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/datacomponent/DataComponentTypes.java
-@@ -0,0 +1,345 @@
-+package io.papermc.paper.datacomponent;
-+
-+import io.papermc.paper.datacomponent.item.BannerPatternLayers;
-+import io.papermc.paper.datacomponent.item.BlockItemDataProperties;
-+import io.papermc.paper.datacomponent.item.BundleContents;
-+import io.papermc.paper.datacomponent.item.ChargedProjectiles;
-+import io.papermc.paper.datacomponent.item.Consumable;
-+import io.papermc.paper.datacomponent.item.CustomModelData;
-+import io.papermc.paper.datacomponent.item.DamageResistant;
-+import io.papermc.paper.datacomponent.item.DeathProtection;
-+import io.papermc.paper.datacomponent.item.DyedItemColor;
-+import io.papermc.paper.datacomponent.item.Enchantable;
-+import io.papermc.paper.datacomponent.item.Equippable;
-+import io.papermc.paper.datacomponent.item.Fireworks;
-+import io.papermc.paper.datacomponent.item.FoodProperties;
-+import io.papermc.paper.datacomponent.item.ItemAdventurePredicate;
-+import io.papermc.paper.datacomponent.item.ItemArmorTrim;
-+import io.papermc.paper.datacomponent.item.ItemAttributeModifiers;
-+import io.papermc.paper.datacomponent.item.ItemContainerContents;
-+import io.papermc.paper.datacomponent.item.ItemEnchantments;
-+import io.papermc.paper.datacomponent.item.ItemLore;
-+import io.papermc.paper.datacomponent.item.JukeboxPlayable;
-+import io.papermc.paper.datacomponent.item.LockCode;
-+import io.papermc.paper.datacomponent.item.LodestoneTracker;
-+import io.papermc.paper.datacomponent.item.MapDecorations;
-+import io.papermc.paper.datacomponent.item.MapId;
-+import io.papermc.paper.datacomponent.item.MapItemColor;
-+import io.papermc.paper.datacomponent.item.OminousBottleAmplifier;
-+import io.papermc.paper.datacomponent.item.PotDecorations;
-+import io.papermc.paper.datacomponent.item.PotionContents;
-+import io.papermc.paper.datacomponent.item.Repairable;
-+import io.papermc.paper.datacomponent.item.ResolvableProfile;
-+import io.papermc.paper.datacomponent.item.SeededContainerLoot;
-+import io.papermc.paper.datacomponent.item.SuspiciousStewEffects;
-+import io.papermc.paper.datacomponent.item.Tool;
-+import io.papermc.paper.datacomponent.item.Unbreakable;
-+import io.papermc.paper.datacomponent.item.UseCooldown;
-+import io.papermc.paper.datacomponent.item.UseRemainder;
-+import io.papermc.paper.datacomponent.item.WritableBookContent;
-+import io.papermc.paper.datacomponent.item.WrittenBookContent;
-+import io.papermc.paper.item.MapPostProcessing;
-+import java.util.List;
-+import net.kyori.adventure.key.Key;
-+import net.kyori.adventure.text.Component;
-+import org.bukkit.DyeColor;
-+import org.bukkit.FireworkEffect;
-+import org.bukkit.MusicInstrument;
-+import org.bukkit.NamespacedKey;
-+import org.bukkit.Registry;
-+import org.bukkit.inventory.ItemRarity;
-+import org.checkerframework.checker.index.qual.NonNegative;
-+import org.checkerframework.checker.index.qual.Positive;
-+import org.checkerframework.common.value.qual.IntRange;
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jspecify.annotations.NullMarked;
-+
-+import static java.util.Objects.requireNonNull;
-+
-+/**
-+ * All the different types of data that {@link org.bukkit.inventory.ItemStack ItemStacks}
-+ * and {@link org.bukkit.inventory.ItemType ItemTypes} can have.
-+ */
-+@NullMarked
-+@ApiStatus.Experimental
-+public final class DataComponentTypes {
-+
-+ // public static final DataComponentType.Valued CUSTOM_DATA = valued("custom_data");
-+ /**
-+ * Controls the maximum stacking size of this item.
-+ *
-+ * Values greater than 1 are mutually exclusive with the {@link #MAX_DAMAGE} component.
-+ */
-+ public static final DataComponentType.Valued<@IntRange(from = 1, to = 99) Integer> MAX_STACK_SIZE = valued("max_stack_size");
-+ /**
-+ * Controls the maximum amount of damage than an item can take,
-+ * if not present, the item cannot be damaged.
-+ *
-+ * Mutually exclusive with the {@link #MAX_STACK_SIZE} component greater than 1.
-+ *
-+ * @see #DAMAGE
-+ */
-+ public static final DataComponentType.Valued<@Positive Integer> MAX_DAMAGE = valued("max_damage");
-+ /**
-+ * The amount of durability removed from an item,
-+ * for damageable items (with the {@link #MAX_DAMAGE} component), has an implicit default value of: {@code 0}.
-+ *
-+ * @see #MAX_DAMAGE
-+ */
-+ public static final DataComponentType.Valued<@NonNegative Integer> DAMAGE = valued("damage");
-+ /**
-+ * If set, the item will not lose any durability when used.
-+ */
-+ public static final DataComponentType.Valued UNBREAKABLE = valued("unbreakable");
-+ /**
-+ * Custom name override for an item (as set by renaming with an Anvil).
-+ *
-+ * @see #ITEM_NAME
-+ */
-+ public static final DataComponentType.Valued CUSTOM_NAME = valued("custom_name");
-+ /**
-+ * When present, replaces default item name with contained chat component.
-+ *
-+ * Differences from {@link #CUSTOM_NAME}:
-+ *
-+ * - can't be changed or removed in Anvil
-+ * - is not styled with italics when displayed to player
-+ * - does not show labels where applicable
-+ * (for example: banner markers, names in item frames)
-+ *
-+ *
-+ * @see #CUSTOM_NAME
-+ */
-+ public static final DataComponentType.Valued ITEM_NAME = valued("item_name");
-+ public static final DataComponentType.Valued ITEM_MODEL = valued("item_model");
-+ /**
-+ * Additional lines to include in an item's tooltip.
-+ */
-+ public static final DataComponentType.Valued LORE = valued("lore");
-+ /**
-+ * Controls the color of the item name.
-+ */
-+ public static final DataComponentType.Valued RARITY = valued("rarity");
-+ /**
-+ * Controls the enchantments on an item.
-+ *
-+ * If not present on a non-enchantment book, this item will not work in an anvil.
-+ *
-+ * @see #STORED_ENCHANTMENTS
-+ */
-+ public static final DataComponentType.Valued ENCHANTMENTS = valued("enchantments");
-+ /**
-+ * Controls which blocks a player in Adventure mode can place on with this item.
-+ */
-+ public static final DataComponentType.Valued CAN_PLACE_ON = valued("can_place_on");
-+ /**
-+ * Controls which blocks a player in Adventure mode can break with this item.
-+ */
-+ public static final DataComponentType.Valued CAN_BREAK = valued("can_break");
-+ /**
-+ * Holds attribute modifiers applied to any item,
-+ * if not set, has an implicit default value based on the item type's
-+ * default attributes (e.g. attack damage for weapons).
-+ */
-+ public static final DataComponentType.Valued ATTRIBUTE_MODIFIERS = valued("attribute_modifiers");
-+ /**
-+ * Controls the minecraft:custom_model_data property in the item model.
-+ */
-+ public static final DataComponentType.Valued CUSTOM_MODEL_DATA = valued("custom_model_data");
-+ /**
-+ * If set, disables 'additional' tooltip part which comes from the item type
-+ * (e.g. content of a shulker).
-+ */
-+ public static final DataComponentType.NonValued HIDE_ADDITIONAL_TOOLTIP = unvalued("hide_additional_tooltip");
-+ /**
-+ * If set, it will completely hide whole item tooltip (that includes item name).
-+ */
-+ public static final DataComponentType.NonValued HIDE_TOOLTIP = unvalued("hide_tooltip");
-+ /**
-+ * The additional experience cost required to modify an item in an Anvil.
-+ * If not present, has an implicit default value of: {@code 0}.
-+ */
-+ public static final DataComponentType.Valued<@NonNegative Integer> REPAIR_COST = valued("repair_cost");
-+ /**
-+ * Causes an item to not be pickable in the creative menu, currently not very useful.
-+ */
-+ public static final DataComponentType.NonValued CREATIVE_SLOT_LOCK = unvalued("creative_slot_lock");
-+ /**
-+ * Overrides the enchantment glint effect on an item.
-+ * If not present, default behaviour is used.
-+ */
-+ public static final DataComponentType.Valued ENCHANTMENT_GLINT_OVERRIDE = valued("enchantment_glint_override");
-+ /**
-+ * Marks that a projectile item would be intangible when fired
-+ * (i.e. can only be picked up by a creative mode player).
-+ */
-+ public static final DataComponentType.NonValued INTANGIBLE_PROJECTILE = unvalued("intangible_projectile");
-+ /**
-+ * When present, this item will behave as if a food (can be eaten).
-+ */
-+ public static final DataComponentType.Valued FOOD = valued("food");
-+ public static final DataComponentType.Valued