diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java
index 5d29a016c..b03e7126a 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java
@@ -35,6 +35,9 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntit
 import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.StringTag;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
 import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.math.vector.Vector3i;
 import org.cloudburstmc.protocol.bedrock.data.AttributeData;
@@ -46,12 +49,10 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket;
 import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket;
 import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.Setter;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.AttributeUtils;
@@ -98,8 +99,7 @@ public class LivingEntity extends Entity {
         boolean isUsingItem = (xd & 0x01) == 0x01;
         boolean isUsingOffhand = (xd & 0x02) == 0x02;
 
-        ItemMapping shield = session.getItemMappings().getStoredItems().shield();
-        boolean isUsingShield = hasShield(isUsingOffhand, shield);
+        boolean isUsingShield = hasShield(isUsingOffhand);
 
         setFlag(EntityFlag.USING_ITEM, isUsingItem && !isUsingShield);
         // Override the blocking
@@ -142,7 +142,8 @@ public class LivingEntity extends Entity {
         }
     }
 
-    protected boolean hasShield(boolean offhand, ItemMapping shieldMapping) {
+    protected boolean hasShield(boolean offhand) {
+        ItemMapping shieldMapping = session.getItemMappings().getStoredItems().shield();
         if (offhand) {
             return offHand.getDefinition().equals(shieldMapping.getBedrockDefinition());
         } else {
@@ -190,7 +191,7 @@ public class LivingEntity extends Entity {
     @Override
     public InteractionResult interact(Hand hand) {
         GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(hand);
-        if (itemStack.getJavaId() == session.getItemMappings().getStoredItems().nameTag().getJavaId()) {
+        if (itemStack.asItem() == Items.NAME_TAG) {
             InteractionResult result = checkInteractWithNameTag(itemStack);
             if (result.consumesAction()) {
                 return result;
@@ -220,10 +221,10 @@ public class LivingEntity extends Entity {
         // If an entity has a banner on them, it will be in the helmet slot in Java but the chestplate spot in Bedrock
         // But don't overwrite the chestplate if it isn't empty
         ItemMapping banner = session.getItemMappings().getStoredItems().banner();
-        if (ItemDefinition.AIR.equals(chestplate.getDefinition()) && helmet.getDefinition().equals(banner.getBedrockDefinition())) {
+        if (ItemDefinition.AIR.equals(chestplate.getDefinition()) && helmet.getDefinition().equals(banner)) {
             chestplate = this.helmet;
             helmet = ItemData.AIR;
-        } else if (chestplate.getDefinition().equals(banner.getBedrockDefinition())) {
+        } else if (chestplate.getDefinition().equals(banner)) {
             // Prevent chestplate banners from showing erroneously
             chestplate = ItemData.AIR;
         }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java
index 75bd34d68..1b5c1d2d0 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java
@@ -35,7 +35,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.GeyserImpl;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.item.Potion;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.EnumSet;
@@ -56,8 +57,8 @@ public class ThrownPotionEntity extends ThrowableItemEntity {
             setFlag(EntityFlag.ENCHANTED, false);
             setFlag(EntityFlag.LINGERING, false);
         } else {
-            ItemMapping mapping = session.getItemMappings().getMapping(itemStack);
-            if (mapping.getJavaIdentifier().endsWith("potion") && itemStack.getNbt() != null) {
+            // As of Java 1.19.3, the server/client doesn't seem to care of the item is actually a potion?
+            if (itemStack.getNbt() != null) {
                 Tag potionTag = itemStack.getNbt().get("Potion");
                 if (potionTag instanceof StringTag) {
                     Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue());
@@ -70,7 +71,7 @@ public class ThrownPotionEntity extends ThrowableItemEntity {
                     }
                 }
 
-                boolean isLingering = mapping.getJavaIdentifier().equals("minecraft:lingering_potion");
+                boolean isLingering = Registries.JAVA_ITEMS.get().get(itemStack.getId()) == Items.LINGERING_POTION;
                 setFlag(EntityFlag.LINGERING, isLingering);
             }
         }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java
index a93cc4f80..f39200eed 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java
@@ -31,6 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -87,6 +88,6 @@ public class AllayEntity extends MobEntity {
     }
 
     private boolean isDuplicationItem(GeyserItemStack itemStack) {
-        return itemStack.getJavaId() == session.getItemMappings().getStoredItems().amethystShard().getJavaId();
+        return itemStack.asItem() == Items.AMETHYST_SHARD;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java
index 9f826f8a2..903f08b64 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java
@@ -39,6 +39,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.EntityDefinitions;
 import org.geysermc.geyser.entity.type.LivingEntity;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.MathUtils;
@@ -247,7 +248,7 @@ public class ArmorStandEntity extends LivingEntity {
 
     @Override
     public InteractionResult interactAt(Hand hand) {
-        if (!isMarker && session.getPlayerInventory().getItemInHand(hand).getJavaId() != session.getItemMappings().getStoredItems().nameTag().getJavaId()) {
+        if (!isMarker && session.getPlayerInventory().getItemInHand(hand).asItem() != Items.NAME_TAG) {
             // Java Edition returns SUCCESS if in spectator mode, but this is overrided with an earlier check on the client
             return InteractionResult.CONSUME;
         } else {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java
index 40b5ad7f5..1f653decd 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java
@@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 
@@ -52,8 +53,8 @@ public class IronGolemEntity extends GolemEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().ironIngot().getJavaId()) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() == Items.IRON_INGOT) {
             if (health < maxHealth) {
                 // Healing the iron golem
                 return InteractionResult.SUCCESS;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java
index fef07a1df..60a9a1474 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java
@@ -27,15 +27,15 @@ package org.geysermc.geyser.entity.type.living;
 
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
 import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
+import lombok.Getter;
 import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
-import lombok.Getter;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.type.LivingEntity;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.inventory.item.StoredItemMappings;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.SpawnEggItem;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -79,11 +79,10 @@ public class MobEntity extends LivingEntity {
             return InteractiveTag.REMOVE_LEASH;
         } else {
             GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(hand);
-            StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
-            if (itemStack.getJavaId() == storedItems.lead().getJavaId() && canBeLeashed()) {
+            if (itemStack.asItem() == Items.LEAD && canBeLeashed()) {
                 // We shall leash
                 return InteractiveTag.LEASH;
-            } else if (itemStack.getJavaId() == storedItems.nameTag().getJavaId()) {
+            } else if (itemStack.asItem() == Items.NAME_TAG) {
                 InteractionResult result = checkInteractWithNameTag(itemStack);
                 if (result.consumesAction()) {
                     return InteractiveTag.NAME;
@@ -116,18 +115,16 @@ public class MobEntity extends LivingEntity {
     }
 
     private InteractionResult checkPriorityInteractions(GeyserItemStack itemInHand) {
-        StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
-        if (itemInHand.getJavaId() == storedItems.lead().getJavaId() && canBeLeashed()) {
+        if (itemInHand.asItem() == Items.LEAD && canBeLeashed()) {
             // We shall leash
             return InteractionResult.SUCCESS;
-        } else if (itemInHand.getJavaId() == storedItems.nameTag().getJavaId()) {
+        } else if (itemInHand.asItem() == Items.NAME_TAG) {
             InteractionResult result = checkInteractWithNameTag(itemInHand);
             if (result.consumesAction()) {
                 return result;
             }
         } else {
-            ItemMapping mapping = itemInHand.getMapping(session);
-            if (mapping.getJavaIdentifier().endsWith("_spawn_egg")) {
+            if (itemInHand.asItem() instanceof SpawnEggItem) {
                 // Using the spawn egg on this entity to create a child
                 return InteractionResult.CONSUME;
             }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java
index c48ca087b..ced274185 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java
@@ -31,6 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -52,8 +53,8 @@ public class SnowGolemEntity extends GolemEntity {
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (session.getItemMappings().getStoredItems().shears().getJavaId() == itemInHand.getJavaId() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (Items.SHEARS == itemInHand.asItem() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
             // Shearing the snow golem
             return InteractiveTag.SHEAR;
         }
@@ -62,8 +63,8 @@ public class SnowGolemEntity extends GolemEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (session.getItemMappings().getStoredItems().shears().getJavaId() == itemInHand.getJavaId() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (Items.SHEARS == itemInHand.asItem() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
             // Shearing the snow golem
             return InteractionResult.SUCCESS;
         }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java
index 6bf4c7757..47ddb9126 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/TadpoleEntity.java
@@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
 import org.cloudburstmc.math.vector.Vector3f;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -61,6 +62,6 @@ public class TadpoleEntity extends AbstractFishEntity {
     }
 
     private boolean isFood(GeyserItemStack itemStack) {
-        return itemStack.getJavaId() == session.getItemMappings().getStoredItems().slimeBall().getJavaId();
+        return itemStack.asItem() == Items.SLIME_BALL;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java
index 6b99cca39..2c46da13b 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java
@@ -32,7 +32,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.type.living.AgeableEntity;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -47,24 +48,20 @@ public class AnimalEntity extends AgeableEntity {
     }
 
     public final boolean canEat(GeyserItemStack itemStack) {
-        ItemMapping mapping = itemStack.getMapping(session);
-        String handIdentifier = mapping.getJavaIdentifier();
-        return canEat(handIdentifier.replace("minecraft:", ""), mapping);
+        return canEat(itemStack.asItem());
     }
 
     /**
-     * @param javaIdentifierStripped the stripped Java identifier of the item that is potential breeding food. For example,
-     *                               <code>wheat</code>.
      * @return true if this is a valid item to breed with for this animal.
      */
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
+    public boolean canEat(Item item) {
         // This is what it defaults to. OK.
-        return javaIdentifierStripped.equals("wheat");
+        return item == Items.WHEAT;
     }
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (canEat(itemInHand)) {
             return InteractiveTag.FEED;
         }
@@ -73,7 +70,7 @@ public class AnimalEntity extends AgeableEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (canEat(itemInHand)) {
             // FEED
             if (getFlag(EntityFlag.BABY)) {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java
index ce21a6836..69abd3bba 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java
@@ -33,7 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.EntityUtils;
 import org.geysermc.geyser.util.InteractionResult;
@@ -60,8 +60,8 @@ public class AxolotlEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return session.getTagCache().isAxolotlTemptItem(mapping);
+    public boolean canEat(Item item) {
+        return session.getTagCache().isAxolotlTemptItem(item);
     }
 
     @Override
@@ -76,7 +76,7 @@ public class AxolotlEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (EntityUtils.attemptToBucket(session, itemInHand)) {
             return InteractionResult.SUCCESS;
         } else {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java
index 46207ab3a..e05b44cf0 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java
@@ -33,7 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.UUID;
@@ -66,7 +66,7 @@ public class BeeEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return session.getTagCache().isFlower(mapping);
+    public boolean canEat(Item item) {
+        return session.getTagCache().isFlower(item);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java
index 959a2f791..164fb1b6c 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java
@@ -27,19 +27,22 @@ package org.geysermc.geyser.entity.type.living.animal;
 
 import org.cloudburstmc.math.vector.Vector3f;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
+import java.util.Set;
 import java.util.UUID;
 
 public class ChickenEntity extends AnimalEntity {
+    private static final Set<Item> VALID_FOOD = Set.of(Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS);
 
     public ChickenEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
         super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.contains("seeds");
+    public boolean canEat(Item item) {
+        return VALID_FOOD.contains(item);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java
index b968f1f6c..01641c8c3 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/CowEntity.java
@@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -45,8 +46,8 @@ public class CowEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (getFlag(EntityFlag.BABY) || itemInHand.asItem() != Items.BUCKET) {
             return super.testMobInteraction(hand, itemInHand);
         }
 
@@ -55,8 +56,8 @@ public class CowEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (getFlag(EntityFlag.BABY) || itemInHand.asItem() != Items.BUCKET) {
             return super.mobInteract(hand, itemInHand);
         }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java
index 417d06444..98c73cbce 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java
@@ -31,7 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.UUID;
@@ -55,7 +55,7 @@ public class FoxEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return session.getTagCache().isFoxFood(mapping);
+    public boolean canEat(Item item) {
+        return session.getTagCache().isFoxFood(item);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java
index 8ed56bf40..039ef5bf9 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FrogEntity.java
@@ -33,7 +33,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.type.Entity;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.OptionalInt;
@@ -75,7 +76,7 @@ public class FrogEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return mapping.getJavaId() == session.getItemMappings().getStoredItems().slimeBall().getJavaId();
+    public boolean canEat(Item item) {
+        return item == Items.SLIME_BALL;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java
index 32517b9b0..20b8f5ccf 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java
@@ -34,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 
@@ -67,10 +68,12 @@ public class GoatEntity extends AnimalEntity {
         }
     }
 
+    // TODO testMobInteraction?
+
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (!getFlag(EntityFlag.BABY) && itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (!getFlag(EntityFlag.BABY) && itemInHand.asItem() == Items.BUCKET) {
             session.playSoundEvent(isScreamer ? SoundEvent.MILK_SCREAMER : SoundEvent.MILK, position);
             return InteractionResult.SUCCESS;
         } else {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java
index d9aeab5ea..154c2f688 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java
@@ -29,7 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
 import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.UUID;
@@ -53,8 +54,8 @@ public class HoglinEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.equals("crimson_fungus");
+    public boolean canEat(Item item) {
+        return item == Items.CRIMSON_FUNGUS;
     }
 
     @Override
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java
index 640bb3d88..c650e0703 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java
@@ -31,7 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.inventory.item.StoredItemMappings;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -53,13 +53,12 @@ public class MooshroomEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (!isBaby()) {
-            if (itemInHand.getJavaId() == storedItems.bowl().getJavaId()) {
+            if (itemInHand.asItem() == Items.BOWL) {
                 // Stew
                 return InteractiveTag.MOOSHROOM_MILK_STEW;
-            } else if (isAlive() && itemInHand.getJavaId() == storedItems.shears().getJavaId()) {
+            } else if (isAlive() && itemInHand.asItem() == Items.SHEARS) {
                 // Shear items
                 return InteractiveTag.MOOSHROOM_SHEAR;
             }
@@ -69,13 +68,12 @@ public class MooshroomEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         boolean isBaby = isBaby();
-        if (!isBaby && itemInHand.getJavaId() == storedItems.bowl().getJavaId()) {
+        if (!isBaby && itemInHand.asItem() == Items.BOWL) {
             // Stew
             return InteractionResult.SUCCESS;
-        } else if (!isBaby && isAlive() && itemInHand.getJavaId() == storedItems.shears().getJavaId()) {
+        } else if (!isBaby && isAlive() && itemInHand.asItem() == Items.SHEARS) {
             // Shear items
             return InteractionResult.SUCCESS;
         } else if (isBrown && session.getTagCache().isSmallFlower(itemInHand) && itemInHand.getMapping(session).isHasSuspiciousStewEffect()) {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java
index 5217e26d7..c81ddd52e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java
@@ -30,7 +30,8 @@ import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -45,8 +46,8 @@ public class OcelotEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
+    public boolean canEat(Item item) {
+        return item == Items.COD || item == Items.SALMON;
     }
 
     @Nonnull
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java
index 6a1d5311c..212eaa91e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java
@@ -35,7 +35,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -88,13 +89,13 @@ public class PandaEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.equals("bamboo");
+    public boolean canEat(Item item) {
+        return item == Items.BAMBOO;
     }
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (mainGene == Gene.WORRIED && session.isThunder()) {
             return InteractiveTag.NONE;
         }
@@ -103,7 +104,7 @@ public class PandaEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (mainGene == Gene.WORRIED && session.isThunder()) {
             // Huh!
             return InteractionResult.PASS;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java
index d2f2f572c..91e94321c 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java
@@ -30,7 +30,8 @@ import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.EntityUtils;
 import org.geysermc.geyser.util.InteractionResult;
@@ -46,13 +47,13 @@ public class PigEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("potato") || javaIdentifierStripped.equals("beetroot");
+    public boolean canEat(Item item) {
+        return item == Items.CARROT || item == Items.POTATO || item == Items.BEETROOT;
     }
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
             // Mount
             return InteractiveTag.MOUNT;
@@ -61,7 +62,7 @@ public class PigEntity extends AnimalEntity {
             if (superTag != InteractiveTag.NONE) {
                 return superTag;
             } else {
-                return EntityUtils.attemptToSaddle(session, this, itemInHand).consumesAction()
+                return EntityUtils.attemptToSaddle(this, itemInHand).consumesAction()
                         ? InteractiveTag.SADDLE : InteractiveTag.NONE;
             }
         }
@@ -69,7 +70,7 @@ public class PigEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
             // Mount
             return InteractionResult.SUCCESS;
@@ -78,7 +79,7 @@ public class PigEntity extends AnimalEntity {
             if (superResult.consumesAction()) {
                 return superResult;
             } else {
-                return EntityUtils.attemptToSaddle(session, this, itemInHand);
+                return EntityUtils.attemptToSaddle(this, itemInHand);
             }
         }
     }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java
index 24220bb79..1d7777cdb 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java
@@ -27,7 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
 
 import org.cloudburstmc.math.vector.Vector3f;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.UUID;
@@ -39,7 +39,7 @@ public class PolarBearEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
+    public boolean canEat(Item item) {
         return false;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java
index 6e9f2181c..c605687fa 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java
@@ -31,7 +31,8 @@ import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.UUID;
@@ -72,7 +73,7 @@ public class RabbitEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.equals("dandelion") || javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("golden_carrot");
+    public boolean canEat(Item item) {
+        return item == Items.DANDELION || item == Items.CARROT || item == Items.GOLDEN_CARROT;
     }
 }
\ No newline at end of file
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java
index c2a12ab59..8c9458012 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java
@@ -32,10 +32,11 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.DyeItem;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
-import org.geysermc.geyser.util.ItemUtils;
 
 import javax.annotation.Nonnull;
 import java.util.UUID;
@@ -56,16 +57,15 @@ public class SheepEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().shears().getJavaId()) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() == Items.SHEARS) {
             return InteractiveTag.SHEAR;
         } else {
             InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
             if (tag != InteractiveTag.NONE) {
                 return tag;
             } else {
-                int color = ItemUtils.dyeColorFor(itemInHand.getJavaId());
-                if (canDye(color)) {
+                if (canDye(itemInHand)) {
                     return InteractiveTag.DYE;
                 }
                 return InteractiveTag.NONE;
@@ -75,16 +75,15 @@ public class SheepEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().shears().getJavaId()) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() == Items.SHEARS) {
             return InteractionResult.CONSUME;
         } else {
             InteractionResult superResult = super.mobInteract(hand, itemInHand);
             if (superResult.consumesAction()) {
                 return superResult;
             } else {
-                int color = ItemUtils.dyeColorFor(itemInHand.getJavaId());
-                if (canDye(color)) {
+                if (canDye(itemInHand)) {
                     // Dyeing the sheep
                     return InteractionResult.SUCCESS;
                 }
@@ -93,7 +92,7 @@ public class SheepEntity extends AnimalEntity {
         }
     }
 
-    private boolean canDye(int color) {
-        return color != -1 && color != this.color && !getFlag(EntityFlag.SHEARED);
+    private boolean canDye(GeyserItemStack item) {
+        return item.asItem() instanceof DyeItem dyeItem && dyeItem.dyeColor() != this.color && !getFlag(EntityFlag.SHEARED);
     }
 }
\ No newline at end of file
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java
index f74bfbfd9..e58fa5aca 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java
@@ -32,7 +32,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.EntityUtils;
 import org.geysermc.geyser.util.InteractionResult;
@@ -93,13 +94,13 @@ public class StriderEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.equals("warped_fungus");
+    public boolean canEat(Item item) {
+        return item == Items.WARPED_FUNGUS;
     }
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
             // Mount Strider
             return InteractiveTag.RIDE_STRIDER;
@@ -108,7 +109,7 @@ public class StriderEntity extends AnimalEntity {
             if (tag != InteractiveTag.NONE) {
                 return tag;
             } else {
-                return EntityUtils.attemptToSaddle(session, this, itemInHand).consumesAction()
+                return EntityUtils.attemptToSaddle(this, itemInHand).consumesAction()
                         ? InteractiveTag.SADDLE : InteractiveTag.NONE;
             }
         }
@@ -116,7 +117,7 @@ public class StriderEntity extends AnimalEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
             // Mount Strider
             return InteractionResult.SUCCESS;
@@ -125,7 +126,7 @@ public class StriderEntity extends AnimalEntity {
             if (superResult.consumesAction()) {
                 return superResult;
             } else {
-                return EntityUtils.attemptToSaddle(session, this, itemInHand);
+                return EntityUtils.attemptToSaddle(this, itemInHand);
             }
         }
     }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java
index c50cf21c5..870ded193 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java
@@ -29,7 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
 import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.UUID;
@@ -49,8 +50,8 @@ public class TurtleEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.equals("seagrass");
+    public boolean canEat(Item item) {
+        return item == Items.SEAGRASS;
     }
 
     @Override
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java
index 7a1cad3e0..872f72190 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java
@@ -27,7 +27,6 @@ package org.geysermc.geyser.entity.type.living.animal.horse;
 
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
 import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
-import com.google.common.collect.ImmutableSet;
 import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
@@ -39,7 +38,8 @@ import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
 import org.geysermc.geyser.entity.type.living.animal.AnimalEntity;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -53,8 +53,8 @@ public class AbstractHorseEntity extends AnimalEntity {
      * A list of all foods a horse/donkey can eat on Java Edition.
      * Used to display interactive tag if needed.
      */
-    private static final Set<String> DONKEY_AND_HORSE_FOODS = ImmutableSet.of("golden_apple", "enchanted_golden_apple",
-            "golden_carrot", "sugar", "apple", "wheat", "hay_block");
+    private static final Set<Item> DONKEY_AND_HORSE_FOODS = Set.of(Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE,
+            Items.GOLDEN_CARROT, Items.SUGAR, Items.APPLE, Items.WHEAT, Items.HAY_BLOCK);
 
     public AbstractHorseEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
         super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
@@ -124,13 +124,13 @@ public class AbstractHorseEntity extends AnimalEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return DONKEY_AND_HORSE_FOODS.contains(javaIdentifierStripped);
+    public boolean canEat(Item item) {
+        return DONKEY_AND_HORSE_FOODS.contains(item);
     }
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         return testHorseInteraction(hand, itemInHand);
     }
 
@@ -165,7 +165,7 @@ public class AbstractHorseEntity extends AnimalEntity {
                 return InteractiveTag.ATTACH_CHEST;
             }
 
-            if (additionalTestForInventoryOpen(itemInHand) || !isBaby && !getFlag(EntityFlag.SADDLED) && itemInHand.getJavaId() == session.getItemMappings().getStoredItems().saddle().getJavaId()) {
+            if (additionalTestForInventoryOpen(itemInHand) || !isBaby && !getFlag(EntityFlag.SADDLED) && itemInHand.asItem() == Items.SADDLE) {
                 // Will open the inventory to be saddled
                 return InteractiveTag.OPEN_CONTAINER;
             }
@@ -221,7 +221,7 @@ public class AbstractHorseEntity extends AnimalEntity {
             }
 
             // Note: yes, this code triggers for llamas too. lol (as of Java Edition 1.18.1)
-            if (additionalTestForInventoryOpen(itemInHand) || (!isBaby && !getFlag(EntityFlag.SADDLED) && itemInHand.getJavaId() == session.getItemMappings().getStoredItems().saddle().getJavaId())) {
+            if (additionalTestForInventoryOpen(itemInHand) || (!isBaby && !getFlag(EntityFlag.SADDLED) && itemInHand.asItem() == Items.SADDLE)) {
                 // Will open the inventory to be saddled
                 return InteractionResult.SUCCESS;
             }
@@ -245,7 +245,7 @@ public class AbstractHorseEntity extends AnimalEntity {
     }
 
     protected boolean additionalTestForInventoryOpen(@Nonnull GeyserItemStack itemInHand) {
-        return itemInHand.getMapping(session).getJavaIdentifier().endsWith("_horse_armor");
+        return itemInHand.asItem().javaIdentifier().endsWith("_horse_armor");
     }
 
     /* Just a place to stuff common code for the undead variants without having duplicate code */
@@ -260,7 +260,7 @@ public class AbstractHorseEntity extends AnimalEntity {
         } else if (!passengers.isEmpty()) {
             return testHorseInteraction(hand, itemInHand);
         } else {
-            if (session.getItemMappings().getStoredItems().saddle().getJavaId() == itemInHand.getJavaId()) {
+            if (Items.SADDLE == itemInHand.asItem()) {
                 return InteractiveTag.OPEN_CONTAINER;
             }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java
index f6cdf451f..ed46cfc2a 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/CamelEntity.java
@@ -30,7 +30,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
 import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.UUID;
@@ -50,8 +51,8 @@ public class CamelEntity extends AbstractHorseEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return "cactus".equals(javaIdentifierStripped);
+    public boolean canEat(Item item) {
+        return item == Items.CACTUS;
     }
 
     @Override
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java
index 708effcd2..0fb9438d2 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java
@@ -29,6 +29,7 @@ import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 
 import javax.annotation.Nonnull;
@@ -53,7 +54,7 @@ public class ChestedHorseEntity extends AbstractHorseEntity {
 
     @Override
     protected boolean testForChest(@Nonnull GeyserItemStack itemInHand) {
-        return itemInHand.getJavaId() == session.getItemMappings().getStoredItems().chest().getJavaId() && !getFlag(EntityFlag.CHESTED);
+        return itemInHand.asItem() == Items.CHEST && !getFlag(EntityFlag.CHESTED);
     }
 
     @Override
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java
index d3d3e8673..a32d7b1b5 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java
@@ -31,7 +31,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.UUID;
@@ -69,7 +70,7 @@ public class LlamaEntity extends ChestedHorseEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.equals("wheat") || javaIdentifierStripped.equals("hay_block");
+    public boolean canEat(Item item) {
+        return item == Items.WHEAT || item == Items.HAY_BLOCK;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java
index ba46224dd..c6718f3df 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java
@@ -34,7 +34,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -100,13 +101,13 @@ public class CatEntity extends TameableEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
-        return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
+    public boolean canEat(Item item) {
+        return item == Items.COD || item == Items.SALMON;
     }
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         boolean tamed = getFlag(EntityFlag.TAMED);
         if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
             // Toggle sitting
@@ -118,7 +119,7 @@ public class CatEntity extends TameableEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         boolean tamed = getFlag(EntityFlag.TAMED);
         if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
             return InteractionResult.SUCCESS;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java
index 3b71b8997..43f379de8 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java
@@ -30,41 +30,44 @@ import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
 
 import javax.annotation.Nonnull;
+import java.util.Set;
 import java.util.UUID;
 
 public class ParrotEntity extends TameableEntity {
+    // Note: is the same as chicken. Reuse?
+    private static final Set<Item> TAMING_FOOD = Set.of(Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS);
 
     public ParrotEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
         super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
+    public boolean canEat(Item item) {
         return false;
     }
 
-    private boolean isTameFood(String javaIdentifierStripped) {
-        return javaIdentifierStripped.contains("seeds");
+    private boolean isTameFood(Item item) {
+        return TAMING_FOOD.contains(item);
     }
 
-    private boolean isPoisonousFood(String javaIdentifierStripped) {
-        return javaIdentifierStripped.equals("cookie");
+    private boolean isPoisonousFood(Item item) {
+        return item == Items.COOKIE;
     }
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        String javaIdentifierStripped = itemInHand.getMapping(session).getJavaIdentifier().replace("minecraft:", "");
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         boolean tame = getFlag(EntityFlag.TAMED);
-        if (!tame && isTameFood(javaIdentifierStripped)) {
+        if (!tame && isTameFood(itemInHand.asItem())) {
             return InteractiveTag.FEED;
-        } else if (isPoisonousFood(javaIdentifierStripped)) {
+        } else if (isPoisonousFood(itemInHand.asItem())) {
             return InteractiveTag.FEED;
         } else if (onGround && tame && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
             // Sitting/standing
@@ -75,12 +78,11 @@ public class ParrotEntity extends TameableEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        String javaIdentifierStripped = itemInHand.getMapping(session).getJavaIdentifier().replace("minecraft:", "");
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         boolean tame = getFlag(EntityFlag.TAMED);
-        if (!tame && isTameFood(javaIdentifierStripped)) {
+        if (!tame && isTameFood(itemInHand.asItem())) {
             return InteractionResult.SUCCESS;
-        } else if (isPoisonousFood(javaIdentifierStripped)) {
+        } else if (isPoisonousFood(itemInHand.asItem())) {
             return InteractionResult.SUCCESS;
         } else if (onGround && tame && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
             // Sitting/standing
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java
index 5ee197c06..ecf0736a3 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java
@@ -28,17 +28,17 @@ package org.geysermc.geyser.entity.type.living.animal.tameable;
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
 import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
-import com.google.common.collect.ImmutableSet;
 import org.cloudburstmc.math.vector.Vector3f;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.DyeItem;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
-import org.geysermc.geyser.util.ItemUtils;
 
 import javax.annotation.Nonnull;
 import java.util.Set;
@@ -48,10 +48,11 @@ public class WolfEntity extends TameableEntity {
     /**
      * A list of all foods a wolf can eat on Java Edition.
      * Used to display interactive tag or particles if needed.
+     * TODO generate
      */
-    private static final Set<String> WOLF_FOODS = ImmutableSet.of("pufferfish", "tropical_fish", "chicken", "cooked_chicken",
-            "porkchop", "beef", "rabbit", "cooked_porkchop", "cooked_beef", "rotten_flesh", "mutton", "cooked_mutton",
-            "cooked_rabbit");
+    private static final Set<Item> WOLF_FOODS = Set.of(Items.PUFFERFISH, Items.TROPICAL_FISH, Items.CHICKEN, Items.COOKED_CHICKEN,
+            Items.PORKCHOP, Items.BEEF, Items.RABBIT, Items.COOKED_PORKCHOP, Items.COOKED_BEEF, Items.ROTTEN_FLESH, Items.MUTTON, Items.COOKED_MUTTON,
+            Items.COOKED_RABBIT);
 
     private byte collarColor;
 
@@ -92,9 +93,9 @@ public class WolfEntity extends TameableEntity {
     }
 
     @Override
-    public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
+    public boolean canEat(Item item) {
         // Cannot be a baby to eat these foods
-        return WOLF_FOODS.contains(javaIdentifierStripped) && !isBaby();
+        return WOLF_FOODS.contains(item) && !isBaby();
     }
 
     @Override
@@ -104,18 +105,17 @@ public class WolfEntity extends TameableEntity {
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (getFlag(EntityFlag.ANGRY)) {
             return InteractiveTag.NONE;
         }
-        if (itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bone") && !getFlag(EntityFlag.TAMED)) {
+        if (itemInHand.asItem() == Items.BONE && !getFlag(EntityFlag.TAMED)) {
             // Bone and untamed - can tame
             return InteractiveTag.TAME;
         } else {
-            int color = ItemUtils.dyeColorFor(itemInHand.getJavaId());
-            if (color != -1) {
+            if (itemInHand.asItem() instanceof DyeItem item) {
                 // If this fails, as of Java Edition 1.18.1, you cannot toggle sit/stand
-                if (color != this.collarColor) {
+                if (item.dyeColor() != this.collarColor) {
                     return InteractiveTag.DYE;
                 }
             } else if (getFlag(EntityFlag.TAMED) && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
@@ -128,9 +128,9 @@ public class WolfEntity extends TameableEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         if (ownerBedrockId == session.getPlayerEntity().getGeyserId() || getFlag(EntityFlag.TAMED)
-                || itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bone") && !getFlag(EntityFlag.ANGRY)) {
+                || itemInHand.asItem() == Items.BONE && !getFlag(EntityFlag.ANGRY)) {
             // Sitting toggle or feeding; not angry
             return InteractionResult.CONSUME;
         } else {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
index 37afd3434..b8465f9ca 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
@@ -32,6 +32,7 @@ import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.EntityDefinitions;
 import org.geysermc.geyser.entity.type.living.AgeableEntity;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -52,9 +53,8 @@ public class AbstractMerchantEntity extends AgeableEntity {
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        String javaIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
-        if (!javaIdentifier.equals("minecraft:villager_spawn_egg")
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() != Items.VILLAGER_SPAWN_EGG
                 && (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING) && ((VillagerEntity) this).isCanTradeWith())) {
             // An additional check we know cannot work
             if (!isBaby()) {
@@ -66,9 +66,8 @@ public class AbstractMerchantEntity extends AgeableEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        String javaIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
-        if (!javaIdentifier.equals("minecraft:villager_spawn_egg")
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() != Items.VILLAGER_SPAWN_EGG
                 && (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING))
                 && (definition != EntityDefinitions.WANDERING_TRADER || !getFlag(EntityFlag.BABY))) {
             // Trading time
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java
index a3cb8436f..4937aa218 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java
@@ -33,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -64,8 +65,8 @@ public class CreeperEntity extends MonsterEntity {
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().flintAndSteel().getJavaId()) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() == Items.FLINT_AND_STEEL) { // TODO now uses item tag
             return InteractiveTag.IGNITE_CREEPER;
         } else {
             return super.testMobInteraction(hand, itemInHand);
@@ -74,8 +75,8 @@ public class CreeperEntity extends MonsterEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().flintAndSteel().getJavaId()) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() == Items.FLINT_AND_STEEL) {
             // Ignite creeper
             session.playSoundEvent(SoundEvent.IGNITE, position);
             return InteractionResult.SUCCESS;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java
index 9cd35e8ce..25fe7f802 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java
@@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -64,7 +65,7 @@ public class PiglinEntity extends BasePiglinEntity {
     @Override
     public void updateOffHand(GeyserSession session) {
         // Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates
-        setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(session.getItemMappings().getMapping(this.offHand)));
+        setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(session.getItemMappings().getMapping(this.offHand).getJavaItem()));
         super.updateBedrockMetadata();
 
         super.updateOffHand(session);
@@ -72,7 +73,7 @@ public class PiglinEntity extends BasePiglinEntity {
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
         if (tag != InteractiveTag.NONE) {
             return tag;
@@ -83,7 +84,7 @@ public class PiglinEntity extends BasePiglinEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
         InteractionResult superResult = super.mobInteract(hand, itemInHand);
         if (superResult.consumesAction()) {
             return superResult;
@@ -93,6 +94,6 @@ public class PiglinEntity extends BasePiglinEntity {
     }
 
     private boolean canGiveGoldTo(@Nonnull GeyserItemStack itemInHand) {
-        return !getFlag(EntityFlag.BABY) && itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldIngot().getJavaId() && !getFlag(EntityFlag.ADMIRING);
+        return !getFlag(EntityFlag.BABY) && itemInHand.asItem() == Items.GOLD_INGOT && !getFlag(EntityFlag.ADMIRING);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java
index 40c8ad232..fbac8663f 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java
@@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.type.living.merchant.VillagerEntity;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.InteractionResult;
 import org.geysermc.geyser.util.InteractiveTag;
@@ -68,8 +69,8 @@ public class ZombieVillagerEntity extends ZombieEntity {
 
     @Nonnull
     @Override
-    protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldenApple().getJavaId()) {
+    protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() == Items.GOLDEN_APPLE) {
             return InteractiveTag.CURE;
         } else {
             return super.testMobInteraction(hand, itemInHand);
@@ -78,8 +79,8 @@ public class ZombieVillagerEntity extends ZombieEntity {
 
     @Nonnull
     @Override
-    protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
-        if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldenApple().getJavaId()) {
+    protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() == Items.GOLDEN_APPLE) {
             // The client doesn't know if the entity has weakness as that's not usually sent over the network
             return InteractionResult.CONSUME;
         } else {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
index 35cad7d6e..4f4654509 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
@@ -38,7 +38,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
 import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
 import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
 import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.util.AttributeUtils;
 import org.geysermc.geyser.util.DimensionUtils;
@@ -189,12 +189,12 @@ public class SessionPlayerEntity extends PlayerEntity {
     }
 
     @Override
-    protected boolean hasShield(boolean offhand, ItemMapping shieldMapping) {
+    protected boolean hasShield(boolean offhand) {
         // Must be overridden to point to the player's inventory cache
         if (offhand) {
-            return session.getPlayerInventory().getOffhand().getJavaId() == shieldMapping.getJavaId();
+            return session.getPlayerInventory().getOffhand().asItem() == Items.SHIELD;
         } else {
-            return session.getPlayerInventory().getItemInHand().getJavaId() == shieldMapping.getJavaId();
+            return session.getPlayerInventory().getItemInHand().asItem() == Items.SHIELD;
         }
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java
index 91ee7c5cb..d76816592 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java
@@ -29,6 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import lombok.Data;
+import org.geysermc.geyser.item.type.Item;
+import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
@@ -105,6 +107,15 @@ public class GeyserItemStack {
         return session.getItemMappings().getMapping(this.javaId);
     }
 
+    private Item item; //TODO
+
+    public Item asItem() {
+        if (item == null) {
+            return (item = Registries.JAVA_ITEMS.get().get(javaId));
+        }
+        return item;
+    }
+
     public boolean isEmpty() {
         return amount <= 0 || javaId == 0;
     }
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java
index a02ce658a..9f8c603e1 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java
@@ -35,6 +35,7 @@ import lombok.Setter;
 import lombok.ToString;
 import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
 import org.geysermc.geyser.GeyserImpl;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
 import org.jetbrains.annotations.Range;
@@ -131,7 +132,7 @@ public abstract class Inventory {
         items[slot] = newItem;
 
         // Lodestone caching
-        if (newItem.getJavaId() == session.getItemMappings().getStoredItems().compass().getJavaId()) {
+        if (newItem.asItem() == Items.COMPASS) {
             CompoundTag nbt = newItem.getNbt();
             if (nbt != null) {
                 Tag lodestoneTag = nbt.get("LodestoneTracked");
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
index 56442f16f..b9652542b 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
@@ -27,6 +27,8 @@ package org.geysermc.geyser.inventory.item;
 
 import lombok.Getter;
 import lombok.experimental.Accessors;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 
 import javax.annotation.Nonnull;
@@ -38,79 +40,45 @@ import java.util.Map;
 @Getter
 @Accessors(fluent = true)
 public class StoredItemMappings {
-    private final ItemMapping amethystShard;
     private final ItemMapping bamboo;
     private final ItemMapping banner;
     private final ItemMapping barrier;
-    private final ItemMapping bowl;
     private final ItemMapping bucket;
-    private final ItemMapping chest;
     private final ItemMapping compass;
     private final ItemMapping crossbow;
-    private final ItemMapping enchantedBook;
-    private final ItemMapping fishingRod;
-    private final ItemMapping flintAndSteel;
     private final ItemMapping frogspawn;
-    private final ItemMapping goatHorn;
     private final ItemMapping glassBottle;
-    private final ItemMapping goldenApple;
-    private final ItemMapping goldIngot;
-    private final ItemMapping ironIngot;
-    private final ItemMapping lead;
     private final ItemMapping lilyPad;
     private final ItemMapping milkBucket;
-    private final ItemMapping nameTag;
     private final ItemMapping powderSnowBucket;
-    private final ItemMapping playerHead;
     private final ItemMapping egg;
-    private final ItemMapping saddle;
-    private final ItemMapping shears;
     private final ItemMapping shield;
-    private final ItemMapping slimeBall;
     private final ItemMapping waterBucket;
     private final ItemMapping wheat;
-    private final ItemMapping writableBook;
 
-    public StoredItemMappings(Map<String, ItemMapping> itemMappings) {
-        this.amethystShard = load(itemMappings, "amethyst_shard");
-        this.bamboo = load(itemMappings, "bamboo");
-        this.banner = load(itemMappings, "white_banner"); // As of 1.17.10, all banners have the same Bedrock ID
-        this.barrier = load(itemMappings, "barrier");
-        this.bowl = load(itemMappings, "bowl");
-        this.bucket = load(itemMappings, "bucket");
-        this.chest = load(itemMappings, "chest");
-        this.compass = load(itemMappings, "compass");
-        this.crossbow = load(itemMappings, "crossbow");
-        this.enchantedBook = load(itemMappings, "enchanted_book");
-        this.fishingRod = load(itemMappings, "fishing_rod");
-        this.flintAndSteel = load(itemMappings, "flint_and_steel");
-        this.frogspawn = load(itemMappings, "frogspawn");
-        this.goatHorn = load(itemMappings, "goat_horn");
-        this.glassBottle = load(itemMappings, "glass_bottle");
-        this.goldenApple = load(itemMappings, "golden_apple");
-        this.goldIngot = load(itemMappings, "gold_ingot");
-        this.ironIngot = load(itemMappings, "iron_ingot");
-        this.lead = load(itemMappings, "lead");
-        this.lilyPad = load(itemMappings, "lily_pad");
-        this.milkBucket = load(itemMappings, "milk_bucket");
-        this.nameTag = load(itemMappings, "name_tag");
-        this.powderSnowBucket = load(itemMappings, "powder_snow_bucket");
-        this.playerHead = load(itemMappings, "player_head");
-        this.egg = load(itemMappings, "egg");
-        this.saddle = load(itemMappings, "saddle");
-        this.shears = load(itemMappings, "shears");
-        this.shield = load(itemMappings, "shield");
-        this.slimeBall = load(itemMappings, "slime_ball");
-        this.waterBucket = load(itemMappings, "water_bucket");
-        this.wheat = load(itemMappings, "wheat");
-        this.writableBook = load(itemMappings, "writable_book");
+    public StoredItemMappings(Map<Item, ItemMapping> itemMappings) {
+        this.bamboo = load(itemMappings, Items.BAMBOO);
+        this.banner = load(itemMappings, Items.WHITE_BANNER); // As of 1.17.10, all banners have the same Bedrock ID
+        this.barrier = load(itemMappings, Items.BARRIER);
+        this.bucket = load(itemMappings, Items.BUCKET);
+        this.compass = load(itemMappings, Items.COMPASS);
+        this.crossbow = load(itemMappings, Items.CROSSBOW);
+        this.frogspawn = load(itemMappings, Items.FROGSPAWN);
+        this.glassBottle = load(itemMappings, Items.GLASS_BOTTLE);
+        this.lilyPad = load(itemMappings, Items.LILY_PAD);
+        this.milkBucket = load(itemMappings, Items.MILK_BUCKET);
+        this.powderSnowBucket = load(itemMappings, Items.POWDER_SNOW_BUCKET);
+        this.egg = load(itemMappings, Items.EGG);
+        this.shield = load(itemMappings, Items.SHIELD);
+        this.waterBucket = load(itemMappings, Items.WATER_BUCKET);
+        this.wheat = load(itemMappings, Items.WHEAT);
     }
 
     @Nonnull
-    private ItemMapping load(Map<String, ItemMapping> itemMappings, String cleanIdentifier) {
-        ItemMapping mapping = itemMappings.get("minecraft:" + cleanIdentifier);
+    private ItemMapping load(Map<Item, ItemMapping> itemMappings, Item item) {
+        ItemMapping mapping = itemMappings.get(item);
         if (mapping == null) {
-            throw new RuntimeException("Could not find item " + cleanIdentifier);
+            throw new RuntimeException("Could not find item " + item.javaIdentifier());
         }
 
         return mapping;
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java
index 6fde01e6b..f8709406b 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java
@@ -44,6 +44,7 @@ import org.geysermc.geyser.inventory.AnvilContainer;
 import org.geysermc.geyser.inventory.GeyserItemStack;
 import org.geysermc.geyser.inventory.Inventory;
 import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.EnchantmentData;
 import org.geysermc.geyser.session.GeyserSession;
@@ -222,9 +223,9 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
         int cost = 0;
         if (!material.isEmpty()) {
             totalRepairCost += getRepairCost(material);
-            if (isCombining(session, input, material)) {
-                if (hasDurability(session, input) && input.getJavaId() == material.getJavaId()) {
-                    cost += calcMergeRepairCost(session, input, material);
+            if (isCombining(input, material)) {
+                if (hasDurability(input) && input.getJavaId() == material.getJavaId()) {
+                    cost += calcMergeRepairCost(input, material);
                 }
 
                 int enchantmentLevelCost = calcMergeEnchantmentCost(session, input, material, bedrock);
@@ -234,8 +235,8 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
                     // Can't repair or merge enchantments
                     return -1;
                 }
-            } else if (hasDurability(session, input) && isRepairing(session, input, material)) {
-                cost = calcRepairLevelCost(session, input, material);
+            } else if (hasDurability(input) && isRepairing(session, input, material)) {
+                cost = calcRepairLevelCost(input, material);
                 if (cost == -1) {
                     // No damage to repair
                     return -1;
@@ -260,21 +261,20 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
      * Calculate the levels needed to repair an item with its repair material
      * E.g. iron_sword + iron_ingot
      *
-     * @param session  Geyser session
      * @param input    an item with durability
      * @param material the item's respective repair material
      * @return the number of levels needed or 0 if it is not possible to repair any further
      */
-    private int calcRepairLevelCost(GeyserSession session, GeyserItemStack input, GeyserItemStack material) {
+    private int calcRepairLevelCost(GeyserItemStack input, GeyserItemStack material) {
         int newDamage = getDamage(input);
-        int unitRepair = Math.min(newDamage, input.getMapping(session).getMaxDamage() / 4);
+        int unitRepair = Math.min(newDamage, input.asItem().maxDamage() / 4);
         if (unitRepair <= 0) {
             // No damage to repair
             return -1;
         }
         for (int i = 0; i < material.getAmount(); i++) {
             newDamage -= unitRepair;
-            unitRepair = Math.min(newDamage, input.getMapping(session).getMaxDamage() / 4);
+            unitRepair = Math.min(newDamage, input.asItem().maxDamage() / 4);
             if (unitRepair <= 0) {
                 return i + 1;
             }
@@ -285,14 +285,13 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
     /**
      * Calculate the levels cost for repairing items by combining two of the same item
      *
-     * @param session  Geyser session
      * @param input    an item with durability
      * @param material a matching item
      * @return the number of levels needed or 0 if it is not possible to repair any further
      */
-    private int calcMergeRepairCost(GeyserSession session, GeyserItemStack input, GeyserItemStack material) {
+    private int calcMergeRepairCost(GeyserItemStack input, GeyserItemStack material) {
         // If the material item is damaged 112% or more, then the input item will not be repaired
-        if (getDamage(input) > 0 && getDamage(material) < (material.getMapping(session).getMaxDamage() * 112 / 100)) {
+        if (getDamage(input) > 0 && getDamage(material) < (material.asItem().maxDamage() * 112 / 100)) {
             return 2;
         }
         return 0;
@@ -319,7 +318,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
                 continue;
             }
 
-            boolean canApply = isEnchantedBook(session, input) || data.validItems().contains(input.getJavaId());
+            boolean canApply = isEnchantedBook(input) || data.validItems().contains(input.getJavaId());
             for (JavaEnchantment incompatible : data.incompatibleEnchantments()) {
                 if (combinedEnchantments.containsKey(incompatible)) {
                     canApply = false;
@@ -342,7 +341,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
                 combinedEnchantments.put(enchantment, newLevel);
 
                 int rarityMultiplier = data.rarityMultiplier();
-                if (isEnchantedBook(session, material) && rarityMultiplier > 1) {
+                if (isEnchantedBook(material) && rarityMultiplier > 1) {
                     rarityMultiplier /= 2;
                 }
                 if (bedrock) {
@@ -376,7 +375,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
         }
         Object2IntMap<JavaEnchantment> enchantments = new Object2IntOpenHashMap<>();
         Tag enchantmentTag;
-        if (isEnchantedBook(session, itemStack)) {
+        if (isEnchantedBook(itemStack)) {
             enchantmentTag = itemStack.getNbt().get("StoredEnchantments");
         } else {
             enchantmentTag = itemStack.getNbt().get("Enchantments");
@@ -408,17 +407,17 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
         return enchantments;
     }
 
-    private boolean isEnchantedBook(GeyserSession session, GeyserItemStack itemStack) {
-        return itemStack.getJavaId() == session.getItemMappings().getStoredItems().enchantedBook().getJavaId();
+    private boolean isEnchantedBook(GeyserItemStack itemStack) {
+        return itemStack.asItem() == Items.ENCHANTED_BOOK;
     }
 
-    private boolean isCombining(GeyserSession session, GeyserItemStack input, GeyserItemStack material) {
-        return isEnchantedBook(session, material) || (input.getJavaId() == material.getJavaId() && hasDurability(session, input));
+    private boolean isCombining(GeyserItemStack input, GeyserItemStack material) {
+        return isEnchantedBook(material) || (input.getJavaId() == material.getJavaId() && hasDurability(input));
     }
 
     private boolean isRepairing(GeyserSession session, GeyserItemStack input, GeyserItemStack material) {
         Set<String> repairMaterials = input.getMapping(session).getRepairMaterials();
-        return repairMaterials != null && repairMaterials.contains(material.getMapping(session).getJavaIdentifier());
+        return repairMaterials != null && repairMaterials.contains(material.asItem().javaIdentifier());
     }
 
     private boolean isRenaming(GeyserSession session, AnvilContainer anvilContainer, boolean bedrock) {
@@ -450,8 +449,8 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
         return getTagIntValueOr(itemStack, "RepairCost", 0);
     }
 
-    private boolean hasDurability(GeyserSession session, GeyserItemStack itemStack) {
-        if (itemStack.getMapping(session).getMaxDamage() > 0) {
+    private boolean hasDurability(GeyserItemStack itemStack) {
+        if (itemStack.asItem().maxDamage() > 0) {
             return getTagIntValueOr(itemStack, "Unbreakable", 0) == 0;
         }
         return false;
diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java
new file mode 100644
index 000000000..fa74c8aca
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/Items.java
@@ -0,0 +1,1237 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.item;
+
+import org.geysermc.geyser.item.type.*;
+import org.geysermc.geyser.registry.Registries;
+
+import static org.geysermc.geyser.item.type.Item.builder;
+
+/**
+ * A list, in order, of all Java items.
+ */
+public final class Items {
+    public static final Item AIR = register(new Item("air", builder()));
+    public static final Item STONE = register(new Item("stone", builder()));
+    public static final Item GRANITE = register(new Item("granite", builder()));
+    public static final Item POLISHED_GRANITE = register(new Item("polished_granite", builder()));
+    public static final Item DIORITE = register(new Item("diorite", builder()));
+    public static final Item POLISHED_DIORITE = register(new Item("polished_diorite", builder()));
+    public static final Item ANDESITE = register(new Item("andesite", builder()));
+    public static final Item POLISHED_ANDESITE = register(new Item("polished_andesite", builder()));
+    public static final Item DEEPSLATE = register(new Item("deepslate", builder()));
+    public static final Item COBBLED_DEEPSLATE = register(new Item("cobbled_deepslate", builder()));
+    public static final Item POLISHED_DEEPSLATE = register(new Item("polished_deepslate", builder()));
+    public static final Item CALCITE = register(new Item("calcite", builder()));
+    public static final Item TUFF = register(new Item("tuff", builder()));
+    public static final Item DRIPSTONE_BLOCK = register(new Item("dripstone_block", builder()));
+    public static final Item GRASS_BLOCK = register(new Item("grass_block", builder()));
+    public static final Item DIRT = register(new Item("dirt", builder()));
+    public static final Item COARSE_DIRT = register(new Item("coarse_dirt", builder()));
+    public static final Item PODZOL = register(new Item("podzol", builder()));
+    public static final Item ROOTED_DIRT = register(new Item("rooted_dirt", builder()));
+    public static final Item MUD = register(new Item("mud", builder()));
+    public static final Item CRIMSON_NYLIUM = register(new Item("crimson_nylium", builder()));
+    public static final Item WARPED_NYLIUM = register(new Item("warped_nylium", builder()));
+    public static final Item COBBLESTONE = register(new Item("cobblestone", builder()));
+    public static final Item OAK_PLANKS = register(new Item("oak_planks", builder()));
+    public static final Item SPRUCE_PLANKS = register(new Item("spruce_planks", builder()));
+    public static final Item BIRCH_PLANKS = register(new Item("birch_planks", builder()));
+    public static final Item JUNGLE_PLANKS = register(new Item("jungle_planks", builder()));
+    public static final Item ACACIA_PLANKS = register(new Item("acacia_planks", builder()));
+    public static final Item DARK_OAK_PLANKS = register(new Item("dark_oak_planks", builder()));
+    public static final Item MANGROVE_PLANKS = register(new Item("mangrove_planks", builder()));
+    public static final Item BAMBOO_PLANKS = register(new Item("bamboo_planks", builder()));
+    public static final Item CRIMSON_PLANKS = register(new Item("crimson_planks", builder()));
+    public static final Item WARPED_PLANKS = register(new Item("warped_planks", builder()));
+    public static final Item BAMBOO_MOSAIC = register(new Item("bamboo_mosaic", builder()));
+    public static final Item OAK_SAPLING = register(new Item("oak_sapling", builder()));
+    public static final Item SPRUCE_SAPLING = register(new Item("spruce_sapling", builder()));
+    public static final Item BIRCH_SAPLING = register(new Item("birch_sapling", builder()));
+    public static final Item JUNGLE_SAPLING = register(new Item("jungle_sapling", builder()));
+    public static final Item ACACIA_SAPLING = register(new Item("acacia_sapling", builder()));
+    public static final Item DARK_OAK_SAPLING = register(new Item("dark_oak_sapling", builder()));
+    public static final Item MANGROVE_PROPAGULE = register(new Item("mangrove_propagule", builder()));
+    public static final Item BEDROCK = register(new Item("bedrock", builder()));
+    public static final Item SAND = register(new Item("sand", builder()));
+    public static final Item RED_SAND = register(new Item("red_sand", builder()));
+    public static final Item GRAVEL = register(new Item("gravel", builder()));
+    public static final Item COAL_ORE = register(new Item("coal_ore", builder()));
+    public static final Item DEEPSLATE_COAL_ORE = register(new Item("deepslate_coal_ore", builder()));
+    public static final Item IRON_ORE = register(new Item("iron_ore", builder()));
+    public static final Item DEEPSLATE_IRON_ORE = register(new Item("deepslate_iron_ore", builder()));
+    public static final Item COPPER_ORE = register(new Item("copper_ore", builder()));
+    public static final Item DEEPSLATE_COPPER_ORE = register(new Item("deepslate_copper_ore", builder()));
+    public static final Item GOLD_ORE = register(new Item("gold_ore", builder()));
+    public static final Item DEEPSLATE_GOLD_ORE = register(new Item("deepslate_gold_ore", builder()));
+    public static final Item REDSTONE_ORE = register(new Item("redstone_ore", builder()));
+    public static final Item DEEPSLATE_REDSTONE_ORE = register(new Item("deepslate_redstone_ore", builder()));
+    public static final Item EMERALD_ORE = register(new Item("emerald_ore", builder()));
+    public static final Item DEEPSLATE_EMERALD_ORE = register(new Item("deepslate_emerald_ore", builder()));
+    public static final Item LAPIS_ORE = register(new Item("lapis_ore", builder()));
+    public static final Item DEEPSLATE_LAPIS_ORE = register(new Item("deepslate_lapis_ore", builder()));
+    public static final Item DIAMOND_ORE = register(new Item("diamond_ore", builder()));
+    public static final Item DEEPSLATE_DIAMOND_ORE = register(new Item("deepslate_diamond_ore", builder()));
+    public static final Item NETHER_GOLD_ORE = register(new Item("nether_gold_ore", builder()));
+    public static final Item NETHER_QUARTZ_ORE = register(new Item("nether_quartz_ore", builder()));
+    public static final Item ANCIENT_DEBRIS = register(new Item("ancient_debris", builder()));
+    public static final Item COAL_BLOCK = register(new Item("coal_block", builder()));
+    public static final Item RAW_IRON_BLOCK = register(new Item("raw_iron_block", builder()));
+    public static final Item RAW_COPPER_BLOCK = register(new Item("raw_copper_block", builder()));
+    public static final Item RAW_GOLD_BLOCK = register(new Item("raw_gold_block", builder()));
+    public static final Item AMETHYST_BLOCK = register(new Item("amethyst_block", builder()));
+    public static final Item BUDDING_AMETHYST = register(new Item("budding_amethyst", builder()));
+    public static final Item IRON_BLOCK = register(new Item("iron_block", builder()));
+    public static final Item COPPER_BLOCK = register(new Item("copper_block", builder()));
+    public static final Item GOLD_BLOCK = register(new Item("gold_block", builder()));
+    public static final Item DIAMOND_BLOCK = register(new Item("diamond_block", builder()));
+    public static final Item NETHERITE_BLOCK = register(new Item("netherite_block", builder()));
+    public static final Item EXPOSED_COPPER = register(new Item("exposed_copper", builder()));
+    public static final Item WEATHERED_COPPER = register(new Item("weathered_copper", builder()));
+    public static final Item OXIDIZED_COPPER = register(new Item("oxidized_copper", builder()));
+    public static final Item CUT_COPPER = register(new Item("cut_copper", builder()));
+    public static final Item EXPOSED_CUT_COPPER = register(new Item("exposed_cut_copper", builder()));
+    public static final Item WEATHERED_CUT_COPPER = register(new Item("weathered_cut_copper", builder()));
+    public static final Item OXIDIZED_CUT_COPPER = register(new Item("oxidized_cut_copper", builder()));
+    public static final Item CUT_COPPER_STAIRS = register(new Item("cut_copper_stairs", builder()));
+    public static final Item EXPOSED_CUT_COPPER_STAIRS = register(new Item("exposed_cut_copper_stairs", builder()));
+    public static final Item WEATHERED_CUT_COPPER_STAIRS = register(new Item("weathered_cut_copper_stairs", builder()));
+    public static final Item OXIDIZED_CUT_COPPER_STAIRS = register(new Item("oxidized_cut_copper_stairs", builder()));
+    public static final Item CUT_COPPER_SLAB = register(new Item("cut_copper_slab", builder()));
+    public static final Item EXPOSED_CUT_COPPER_SLAB = register(new Item("exposed_cut_copper_slab", builder()));
+    public static final Item WEATHERED_CUT_COPPER_SLAB = register(new Item("weathered_cut_copper_slab", builder()));
+    public static final Item OXIDIZED_CUT_COPPER_SLAB = register(new Item("oxidized_cut_copper_slab", builder()));
+    public static final Item WAXED_COPPER_BLOCK = register(new Item("waxed_copper_block", builder()));
+    public static final Item WAXED_EXPOSED_COPPER = register(new Item("waxed_exposed_copper", builder()));
+    public static final Item WAXED_WEATHERED_COPPER = register(new Item("waxed_weathered_copper", builder()));
+    public static final Item WAXED_OXIDIZED_COPPER = register(new Item("waxed_oxidized_copper", builder()));
+    public static final Item WAXED_CUT_COPPER = register(new Item("waxed_cut_copper", builder()));
+    public static final Item WAXED_EXPOSED_CUT_COPPER = register(new Item("waxed_exposed_cut_copper", builder()));
+    public static final Item WAXED_WEATHERED_CUT_COPPER = register(new Item("waxed_weathered_cut_copper", builder()));
+    public static final Item WAXED_OXIDIZED_CUT_COPPER = register(new Item("waxed_oxidized_cut_copper", builder()));
+    public static final Item WAXED_CUT_COPPER_STAIRS = register(new Item("waxed_cut_copper_stairs", builder()));
+    public static final Item WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new Item("waxed_exposed_cut_copper_stairs", builder()));
+    public static final Item WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new Item("waxed_weathered_cut_copper_stairs", builder()));
+    public static final Item WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new Item("waxed_oxidized_cut_copper_stairs", builder()));
+    public static final Item WAXED_CUT_COPPER_SLAB = register(new Item("waxed_cut_copper_slab", builder()));
+    public static final Item WAXED_EXPOSED_CUT_COPPER_SLAB = register(new Item("waxed_exposed_cut_copper_slab", builder()));
+    public static final Item WAXED_WEATHERED_CUT_COPPER_SLAB = register(new Item("waxed_weathered_cut_copper_slab", builder()));
+    public static final Item WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new Item("waxed_oxidized_cut_copper_slab", builder()));
+    public static final Item OAK_LOG = register(new Item("oak_log", builder()));
+    public static final Item SPRUCE_LOG = register(new Item("spruce_log", builder()));
+    public static final Item BIRCH_LOG = register(new Item("birch_log", builder()));
+    public static final Item JUNGLE_LOG = register(new Item("jungle_log", builder()));
+    public static final Item ACACIA_LOG = register(new Item("acacia_log", builder()));
+    public static final Item DARK_OAK_LOG = register(new Item("dark_oak_log", builder()));
+    public static final Item MANGROVE_LOG = register(new Item("mangrove_log", builder()));
+    public static final Item MANGROVE_ROOTS = register(new Item("mangrove_roots", builder()));
+    public static final Item MUDDY_MANGROVE_ROOTS = register(new Item("muddy_mangrove_roots", builder()));
+    public static final Item CRIMSON_STEM = register(new Item("crimson_stem", builder()));
+    public static final Item WARPED_STEM = register(new Item("warped_stem", builder()));
+    public static final Item BAMBOO_BLOCK = register(new Item("bamboo_block", builder()));
+    public static final Item STRIPPED_OAK_LOG = register(new Item("stripped_oak_log", builder()));
+    public static final Item STRIPPED_SPRUCE_LOG = register(new Item("stripped_spruce_log", builder()));
+    public static final Item STRIPPED_BIRCH_LOG = register(new Item("stripped_birch_log", builder()));
+    public static final Item STRIPPED_JUNGLE_LOG = register(new Item("stripped_jungle_log", builder()));
+    public static final Item STRIPPED_ACACIA_LOG = register(new Item("stripped_acacia_log", builder()));
+    public static final Item STRIPPED_DARK_OAK_LOG = register(new Item("stripped_dark_oak_log", builder()));
+    public static final Item STRIPPED_MANGROVE_LOG = register(new Item("stripped_mangrove_log", builder()));
+    public static final Item STRIPPED_CRIMSON_STEM = register(new Item("stripped_crimson_stem", builder()));
+    public static final Item STRIPPED_WARPED_STEM = register(new Item("stripped_warped_stem", builder()));
+    public static final Item STRIPPED_OAK_WOOD = register(new Item("stripped_oak_wood", builder()));
+    public static final Item STRIPPED_SPRUCE_WOOD = register(new Item("stripped_spruce_wood", builder()));
+    public static final Item STRIPPED_BIRCH_WOOD = register(new Item("stripped_birch_wood", builder()));
+    public static final Item STRIPPED_JUNGLE_WOOD = register(new Item("stripped_jungle_wood", builder()));
+    public static final Item STRIPPED_ACACIA_WOOD = register(new Item("stripped_acacia_wood", builder()));
+    public static final Item STRIPPED_DARK_OAK_WOOD = register(new Item("stripped_dark_oak_wood", builder()));
+    public static final Item STRIPPED_MANGROVE_WOOD = register(new Item("stripped_mangrove_wood", builder()));
+    public static final Item STRIPPED_CRIMSON_HYPHAE = register(new Item("stripped_crimson_hyphae", builder()));
+    public static final Item STRIPPED_WARPED_HYPHAE = register(new Item("stripped_warped_hyphae", builder()));
+    public static final Item STRIPPED_BAMBOO_BLOCK = register(new Item("stripped_bamboo_block", builder()));
+    public static final Item OAK_WOOD = register(new Item("oak_wood", builder()));
+    public static final Item SPRUCE_WOOD = register(new Item("spruce_wood", builder()));
+    public static final Item BIRCH_WOOD = register(new Item("birch_wood", builder()));
+    public static final Item JUNGLE_WOOD = register(new Item("jungle_wood", builder()));
+    public static final Item ACACIA_WOOD = register(new Item("acacia_wood", builder()));
+    public static final Item DARK_OAK_WOOD = register(new Item("dark_oak_wood", builder()));
+    public static final Item MANGROVE_WOOD = register(new Item("mangrove_wood", builder()));
+    public static final Item CRIMSON_HYPHAE = register(new Item("crimson_hyphae", builder()));
+    public static final Item WARPED_HYPHAE = register(new Item("warped_hyphae", builder()));
+    public static final Item OAK_LEAVES = register(new Item("oak_leaves", builder()));
+    public static final Item SPRUCE_LEAVES = register(new Item("spruce_leaves", builder()));
+    public static final Item BIRCH_LEAVES = register(new Item("birch_leaves", builder()));
+    public static final Item JUNGLE_LEAVES = register(new Item("jungle_leaves", builder()));
+    public static final Item ACACIA_LEAVES = register(new Item("acacia_leaves", builder()));
+    public static final Item DARK_OAK_LEAVES = register(new Item("dark_oak_leaves", builder()));
+    public static final Item MANGROVE_LEAVES = register(new Item("mangrove_leaves", builder()));
+    public static final Item AZALEA_LEAVES = register(new Item("azalea_leaves", builder()));
+    public static final Item FLOWERING_AZALEA_LEAVES = register(new Item("flowering_azalea_leaves", builder()));
+    public static final Item SPONGE = register(new Item("sponge", builder()));
+    public static final Item WET_SPONGE = register(new Item("wet_sponge", builder()));
+    public static final Item GLASS = register(new Item("glass", builder()));
+    public static final Item TINTED_GLASS = register(new Item("tinted_glass", builder()));
+    public static final Item LAPIS_BLOCK = register(new Item("lapis_block", builder()));
+    public static final Item SANDSTONE = register(new Item("sandstone", builder()));
+    public static final Item CHISELED_SANDSTONE = register(new Item("chiseled_sandstone", builder()));
+    public static final Item CUT_SANDSTONE = register(new Item("cut_sandstone", builder()));
+    public static final Item COBWEB = register(new Item("cobweb", builder()));
+    public static final Item GRASS = register(new Item("grass", builder()));
+    public static final Item FERN = register(new Item("fern", builder()));
+    public static final Item AZALEA = register(new Item("azalea", builder()));
+    public static final Item FLOWERING_AZALEA = register(new Item("flowering_azalea", builder()));
+    public static final Item DEAD_BUSH = register(new Item("dead_bush", builder()));
+    public static final Item SEAGRASS = register(new Item("seagrass", builder()));
+    public static final Item SEA_PICKLE = register(new Item("sea_pickle", builder()));
+    public static final Item WHITE_WOOL = register(new Item("white_wool", builder()));
+    public static final Item ORANGE_WOOL = register(new Item("orange_wool", builder()));
+    public static final Item MAGENTA_WOOL = register(new Item("magenta_wool", builder()));
+    public static final Item LIGHT_BLUE_WOOL = register(new Item("light_blue_wool", builder()));
+    public static final Item YELLOW_WOOL = register(new Item("yellow_wool", builder()));
+    public static final Item LIME_WOOL = register(new Item("lime_wool", builder()));
+    public static final Item PINK_WOOL = register(new Item("pink_wool", builder()));
+    public static final Item GRAY_WOOL = register(new Item("gray_wool", builder()));
+    public static final Item LIGHT_GRAY_WOOL = register(new Item("light_gray_wool", builder()));
+    public static final Item CYAN_WOOL = register(new Item("cyan_wool", builder()));
+    public static final Item PURPLE_WOOL = register(new Item("purple_wool", builder()));
+    public static final Item BLUE_WOOL = register(new Item("blue_wool", builder()));
+    public static final Item BROWN_WOOL = register(new Item("brown_wool", builder()));
+    public static final Item GREEN_WOOL = register(new Item("green_wool", builder()));
+    public static final Item RED_WOOL = register(new Item("red_wool", builder()));
+    public static final Item BLACK_WOOL = register(new Item("black_wool", builder()));
+    public static final Item DANDELION = register(new Item("dandelion", builder()));
+    public static final Item POPPY = register(new Item("poppy", builder()));
+    public static final Item BLUE_ORCHID = register(new Item("blue_orchid", builder()));
+    public static final Item ALLIUM = register(new Item("allium", builder()));
+    public static final Item AZURE_BLUET = register(new Item("azure_bluet", builder()));
+    public static final Item RED_TULIP = register(new Item("red_tulip", builder()));
+    public static final Item ORANGE_TULIP = register(new Item("orange_tulip", builder()));
+    public static final Item WHITE_TULIP = register(new Item("white_tulip", builder()));
+    public static final Item PINK_TULIP = register(new Item("pink_tulip", builder()));
+    public static final Item OXEYE_DAISY = register(new Item("oxeye_daisy", builder()));
+    public static final Item CORNFLOWER = register(new Item("cornflower", builder()));
+    public static final Item LILY_OF_THE_VALLEY = register(new Item("lily_of_the_valley", builder()));
+    public static final Item WITHER_ROSE = register(new Item("wither_rose", builder()));
+    public static final Item SPORE_BLOSSOM = register(new Item("spore_blossom", builder()));
+    public static final Item BROWN_MUSHROOM = register(new Item("brown_mushroom", builder()));
+    public static final Item RED_MUSHROOM = register(new Item("red_mushroom", builder()));
+    public static final Item CRIMSON_FUNGUS = register(new Item("crimson_fungus", builder()));
+    public static final Item WARPED_FUNGUS = register(new Item("warped_fungus", builder()));
+    public static final Item CRIMSON_ROOTS = register(new Item("crimson_roots", builder()));
+    public static final Item WARPED_ROOTS = register(new Item("warped_roots", builder()));
+    public static final Item NETHER_SPROUTS = register(new Item("nether_sprouts", builder()));
+    public static final Item WEEPING_VINES = register(new Item("weeping_vines", builder()));
+    public static final Item TWISTING_VINES = register(new Item("twisting_vines", builder()));
+    public static final Item SUGAR_CANE = register(new Item("sugar_cane", builder()));
+    public static final Item KELP = register(new Item("kelp", builder()));
+    public static final Item MOSS_CARPET = register(new Item("moss_carpet", builder()));
+    public static final Item MOSS_BLOCK = register(new Item("moss_block", builder()));
+    public static final Item HANGING_ROOTS = register(new Item("hanging_roots", builder()));
+    public static final Item BIG_DRIPLEAF = register(new Item("big_dripleaf", builder()));
+    public static final Item SMALL_DRIPLEAF = register(new Item("small_dripleaf", builder()));
+    public static final Item BAMBOO = register(new Item("bamboo", builder()));
+    public static final Item OAK_SLAB = register(new Item("oak_slab", builder()));
+    public static final Item SPRUCE_SLAB = register(new Item("spruce_slab", builder()));
+    public static final Item BIRCH_SLAB = register(new Item("birch_slab", builder()));
+    public static final Item JUNGLE_SLAB = register(new Item("jungle_slab", builder()));
+    public static final Item ACACIA_SLAB = register(new Item("acacia_slab", builder()));
+    public static final Item DARK_OAK_SLAB = register(new Item("dark_oak_slab", builder()));
+    public static final Item MANGROVE_SLAB = register(new Item("mangrove_slab", builder()));
+    public static final Item BAMBOO_SLAB = register(new Item("bamboo_slab", builder()));
+    public static final Item BAMBOO_MOSAIC_SLAB = register(new Item("bamboo_mosaic_slab", builder()));
+    public static final Item CRIMSON_SLAB = register(new Item("crimson_slab", builder()));
+    public static final Item WARPED_SLAB = register(new Item("warped_slab", builder()));
+    public static final Item STONE_SLAB = register(new Item("stone_slab", builder()));
+    public static final Item SMOOTH_STONE_SLAB = register(new Item("smooth_stone_slab", builder()));
+    public static final Item SANDSTONE_SLAB = register(new Item("sandstone_slab", builder()));
+    public static final Item CUT_SANDSTONE_SLAB = register(new Item("cut_sandstone_slab", builder()));
+    public static final Item PETRIFIED_OAK_SLAB = register(new Item("petrified_oak_slab", builder()));
+    public static final Item COBBLESTONE_SLAB = register(new Item("cobblestone_slab", builder()));
+    public static final Item BRICK_SLAB = register(new Item("brick_slab", builder()));
+    public static final Item STONE_BRICK_SLAB = register(new Item("stone_brick_slab", builder()));
+    public static final Item MUD_BRICK_SLAB = register(new Item("mud_brick_slab", builder()));
+    public static final Item NETHER_BRICK_SLAB = register(new Item("nether_brick_slab", builder()));
+    public static final Item QUARTZ_SLAB = register(new Item("quartz_slab", builder()));
+    public static final Item RED_SANDSTONE_SLAB = register(new Item("red_sandstone_slab", builder()));
+    public static final Item CUT_RED_SANDSTONE_SLAB = register(new Item("cut_red_sandstone_slab", builder()));
+    public static final Item PURPUR_SLAB = register(new Item("purpur_slab", builder()));
+    public static final Item PRISMARINE_SLAB = register(new Item("prismarine_slab", builder()));
+    public static final Item PRISMARINE_BRICK_SLAB = register(new Item("prismarine_brick_slab", builder()));
+    public static final Item DARK_PRISMARINE_SLAB = register(new Item("dark_prismarine_slab", builder()));
+    public static final Item SMOOTH_QUARTZ = register(new Item("smooth_quartz", builder()));
+    public static final Item SMOOTH_RED_SANDSTONE = register(new Item("smooth_red_sandstone", builder()));
+    public static final Item SMOOTH_SANDSTONE = register(new Item("smooth_sandstone", builder()));
+    public static final Item SMOOTH_STONE = register(new Item("smooth_stone", builder()));
+    public static final Item BRICKS = register(new Item("bricks", builder()));
+    public static final Item BOOKSHELF = register(new Item("bookshelf", builder()));
+    public static final Item CHISELED_BOOKSHELF = register(new Item("chiseled_bookshelf", builder()));
+    public static final Item MOSSY_COBBLESTONE = register(new Item("mossy_cobblestone", builder()));
+    public static final Item OBSIDIAN = register(new Item("obsidian", builder()));
+    public static final Item TORCH = register(new Item("torch", builder()));
+    public static final Item END_ROD = register(new Item("end_rod", builder()));
+    public static final Item CHORUS_PLANT = register(new Item("chorus_plant", builder()));
+    public static final Item CHORUS_FLOWER = register(new Item("chorus_flower", builder()));
+    public static final Item PURPUR_BLOCK = register(new Item("purpur_block", builder()));
+    public static final Item PURPUR_PILLAR = register(new Item("purpur_pillar", builder()));
+    public static final Item PURPUR_STAIRS = register(new Item("purpur_stairs", builder()));
+    public static final Item SPAWNER = register(new Item("spawner", builder()));
+    public static final Item CHEST = register(new Item("chest", builder()));
+    public static final Item CRAFTING_TABLE = register(new Item("crafting_table", builder()));
+    public static final Item FARMLAND = register(new Item("farmland", builder()));
+    public static final Item FURNACE = register(new Item("furnace", builder()));
+    public static final Item LADDER = register(new Item("ladder", builder()));
+    public static final Item COBBLESTONE_STAIRS = register(new Item("cobblestone_stairs", builder()));
+    public static final Item SNOW = register(new Item("snow", builder()));
+    public static final Item ICE = register(new Item("ice", builder()));
+    public static final Item SNOW_BLOCK = register(new Item("snow_block", builder()));
+    public static final Item CACTUS = register(new Item("cactus", builder()));
+    public static final Item CLAY = register(new Item("clay", builder()));
+    public static final Item JUKEBOX = register(new Item("jukebox", builder()));
+    public static final Item OAK_FENCE = register(new Item("oak_fence", builder()));
+    public static final Item SPRUCE_FENCE = register(new Item("spruce_fence", builder()));
+    public static final Item BIRCH_FENCE = register(new Item("birch_fence", builder()));
+    public static final Item JUNGLE_FENCE = register(new Item("jungle_fence", builder()));
+    public static final Item ACACIA_FENCE = register(new Item("acacia_fence", builder()));
+    public static final Item DARK_OAK_FENCE = register(new Item("dark_oak_fence", builder()));
+    public static final Item MANGROVE_FENCE = register(new Item("mangrove_fence", builder()));
+    public static final Item BAMBOO_FENCE = register(new Item("bamboo_fence", builder()));
+    public static final Item CRIMSON_FENCE = register(new Item("crimson_fence", builder()));
+    public static final Item WARPED_FENCE = register(new Item("warped_fence", builder()));
+    public static final Item PUMPKIN = register(new Item("pumpkin", builder()));
+    public static final Item CARVED_PUMPKIN = register(new Item("carved_pumpkin", builder()));
+    public static final Item JACK_O_LANTERN = register(new Item("jack_o_lantern", builder()));
+    public static final Item NETHERRACK = register(new Item("netherrack", builder()));
+    public static final Item SOUL_SAND = register(new Item("soul_sand", builder()));
+    public static final Item SOUL_SOIL = register(new Item("soul_soil", builder()));
+    public static final Item BASALT = register(new Item("basalt", builder()));
+    public static final Item POLISHED_BASALT = register(new Item("polished_basalt", builder()));
+    public static final Item SMOOTH_BASALT = register(new Item("smooth_basalt", builder()));
+    public static final Item SOUL_TORCH = register(new Item("soul_torch", builder()));
+    public static final Item GLOWSTONE = register(new Item("glowstone", builder()));
+    public static final Item INFESTED_STONE = register(new Item("infested_stone", builder()));
+    public static final Item INFESTED_COBBLESTONE = register(new Item("infested_cobblestone", builder()));
+    public static final Item INFESTED_STONE_BRICKS = register(new Item("infested_stone_bricks", builder()));
+    public static final Item INFESTED_MOSSY_STONE_BRICKS = register(new Item("infested_mossy_stone_bricks", builder()));
+    public static final Item INFESTED_CRACKED_STONE_BRICKS = register(new Item("infested_cracked_stone_bricks", builder()));
+    public static final Item INFESTED_CHISELED_STONE_BRICKS = register(new Item("infested_chiseled_stone_bricks", builder()));
+    public static final Item INFESTED_DEEPSLATE = register(new Item("infested_deepslate", builder()));
+    public static final Item STONE_BRICKS = register(new Item("stone_bricks", builder()));
+    public static final Item MOSSY_STONE_BRICKS = register(new Item("mossy_stone_bricks", builder()));
+    public static final Item CRACKED_STONE_BRICKS = register(new Item("cracked_stone_bricks", builder()));
+    public static final Item CHISELED_STONE_BRICKS = register(new Item("chiseled_stone_bricks", builder()));
+    public static final Item PACKED_MUD = register(new Item("packed_mud", builder()));
+    public static final Item MUD_BRICKS = register(new Item("mud_bricks", builder()));
+    public static final Item DEEPSLATE_BRICKS = register(new Item("deepslate_bricks", builder()));
+    public static final Item CRACKED_DEEPSLATE_BRICKS = register(new Item("cracked_deepslate_bricks", builder()));
+    public static final Item DEEPSLATE_TILES = register(new Item("deepslate_tiles", builder()));
+    public static final Item CRACKED_DEEPSLATE_TILES = register(new Item("cracked_deepslate_tiles", builder()));
+    public static final Item CHISELED_DEEPSLATE = register(new Item("chiseled_deepslate", builder()));
+    public static final Item REINFORCED_DEEPSLATE = register(new Item("reinforced_deepslate", builder()));
+    public static final Item BROWN_MUSHROOM_BLOCK = register(new Item("brown_mushroom_block", builder()));
+    public static final Item RED_MUSHROOM_BLOCK = register(new Item("red_mushroom_block", builder()));
+    public static final Item MUSHROOM_STEM = register(new Item("mushroom_stem", builder()));
+    public static final Item IRON_BARS = register(new Item("iron_bars", builder()));
+    public static final Item CHAIN = register(new Item("chain", builder()));
+    public static final Item GLASS_PANE = register(new Item("glass_pane", builder()));
+    public static final Item MELON = register(new Item("melon", builder()));
+    public static final Item VINE = register(new Item("vine", builder()));
+    public static final Item GLOW_LICHEN = register(new Item("glow_lichen", builder()));
+    public static final Item BRICK_STAIRS = register(new Item("brick_stairs", builder()));
+    public static final Item STONE_BRICK_STAIRS = register(new Item("stone_brick_stairs", builder()));
+    public static final Item MUD_BRICK_STAIRS = register(new Item("mud_brick_stairs", builder()));
+    public static final Item MYCELIUM = register(new Item("mycelium", builder()));
+    public static final Item LILY_PAD = register(new Item("lily_pad", builder()));
+    public static final Item NETHER_BRICKS = register(new Item("nether_bricks", builder()));
+    public static final Item CRACKED_NETHER_BRICKS = register(new Item("cracked_nether_bricks", builder()));
+    public static final Item CHISELED_NETHER_BRICKS = register(new Item("chiseled_nether_bricks", builder()));
+    public static final Item NETHER_BRICK_FENCE = register(new Item("nether_brick_fence", builder()));
+    public static final Item NETHER_BRICK_STAIRS = register(new Item("nether_brick_stairs", builder()));
+    public static final Item SCULK = register(new Item("sculk", builder()));
+    public static final Item SCULK_VEIN = register(new Item("sculk_vein", builder()));
+    public static final Item SCULK_CATALYST = register(new Item("sculk_catalyst", builder()));
+    public static final Item SCULK_SHRIEKER = register(new Item("sculk_shrieker", builder()));
+    public static final Item ENCHANTING_TABLE = register(new Item("enchanting_table", builder()));
+    public static final Item END_PORTAL_FRAME = register(new Item("end_portal_frame", builder()));
+    public static final Item END_STONE = register(new Item("end_stone", builder()));
+    public static final Item END_STONE_BRICKS = register(new Item("end_stone_bricks", builder()));
+    public static final Item DRAGON_EGG = register(new Item("dragon_egg", builder()));
+    public static final Item SANDSTONE_STAIRS = register(new Item("sandstone_stairs", builder()));
+    public static final Item ENDER_CHEST = register(new Item("ender_chest", builder()));
+    public static final Item EMERALD_BLOCK = register(new Item("emerald_block", builder()));
+    public static final Item OAK_STAIRS = register(new Item("oak_stairs", builder()));
+    public static final Item SPRUCE_STAIRS = register(new Item("spruce_stairs", builder()));
+    public static final Item BIRCH_STAIRS = register(new Item("birch_stairs", builder()));
+    public static final Item JUNGLE_STAIRS = register(new Item("jungle_stairs", builder()));
+    public static final Item ACACIA_STAIRS = register(new Item("acacia_stairs", builder()));
+    public static final Item DARK_OAK_STAIRS = register(new Item("dark_oak_stairs", builder()));
+    public static final Item MANGROVE_STAIRS = register(new Item("mangrove_stairs", builder()));
+    public static final Item BAMBOO_STAIRS = register(new Item("bamboo_stairs", builder()));
+    public static final Item BAMBOO_MOSAIC_STAIRS = register(new Item("bamboo_mosaic_stairs", builder()));
+    public static final Item CRIMSON_STAIRS = register(new Item("crimson_stairs", builder()));
+    public static final Item WARPED_STAIRS = register(new Item("warped_stairs", builder()));
+    public static final Item COMMAND_BLOCK = register(new Item("command_block", builder()));
+    public static final Item BEACON = register(new Item("beacon", builder()));
+    public static final Item COBBLESTONE_WALL = register(new Item("cobblestone_wall", builder()));
+    public static final Item MOSSY_COBBLESTONE_WALL = register(new Item("mossy_cobblestone_wall", builder()));
+    public static final Item BRICK_WALL = register(new Item("brick_wall", builder()));
+    public static final Item PRISMARINE_WALL = register(new Item("prismarine_wall", builder()));
+    public static final Item RED_SANDSTONE_WALL = register(new Item("red_sandstone_wall", builder()));
+    public static final Item MOSSY_STONE_BRICK_WALL = register(new Item("mossy_stone_brick_wall", builder()));
+    public static final Item GRANITE_WALL = register(new Item("granite_wall", builder()));
+    public static final Item STONE_BRICK_WALL = register(new Item("stone_brick_wall", builder()));
+    public static final Item MUD_BRICK_WALL = register(new Item("mud_brick_wall", builder()));
+    public static final Item NETHER_BRICK_WALL = register(new Item("nether_brick_wall", builder()));
+    public static final Item ANDESITE_WALL = register(new Item("andesite_wall", builder()));
+    public static final Item RED_NETHER_BRICK_WALL = register(new Item("red_nether_brick_wall", builder()));
+    public static final Item SANDSTONE_WALL = register(new Item("sandstone_wall", builder()));
+    public static final Item END_STONE_BRICK_WALL = register(new Item("end_stone_brick_wall", builder()));
+    public static final Item DIORITE_WALL = register(new Item("diorite_wall", builder()));
+    public static final Item BLACKSTONE_WALL = register(new Item("blackstone_wall", builder()));
+    public static final Item POLISHED_BLACKSTONE_WALL = register(new Item("polished_blackstone_wall", builder()));
+    public static final Item POLISHED_BLACKSTONE_BRICK_WALL = register(new Item("polished_blackstone_brick_wall", builder()));
+    public static final Item COBBLED_DEEPSLATE_WALL = register(new Item("cobbled_deepslate_wall", builder()));
+    public static final Item POLISHED_DEEPSLATE_WALL = register(new Item("polished_deepslate_wall", builder()));
+    public static final Item DEEPSLATE_BRICK_WALL = register(new Item("deepslate_brick_wall", builder()));
+    public static final Item DEEPSLATE_TILE_WALL = register(new Item("deepslate_tile_wall", builder()));
+    public static final Item ANVIL = register(new Item("anvil", builder()));
+    public static final Item CHIPPED_ANVIL = register(new Item("chipped_anvil", builder()));
+    public static final Item DAMAGED_ANVIL = register(new Item("damaged_anvil", builder()));
+    public static final Item CHISELED_QUARTZ_BLOCK = register(new Item("chiseled_quartz_block", builder()));
+    public static final Item QUARTZ_BLOCK = register(new Item("quartz_block", builder()));
+    public static final Item QUARTZ_BRICKS = register(new Item("quartz_bricks", builder()));
+    public static final Item QUARTZ_PILLAR = register(new Item("quartz_pillar", builder()));
+    public static final Item QUARTZ_STAIRS = register(new Item("quartz_stairs", builder()));
+    public static final Item WHITE_TERRACOTTA = register(new Item("white_terracotta", builder()));
+    public static final Item ORANGE_TERRACOTTA = register(new Item("orange_terracotta", builder()));
+    public static final Item MAGENTA_TERRACOTTA = register(new Item("magenta_terracotta", builder()));
+    public static final Item LIGHT_BLUE_TERRACOTTA = register(new Item("light_blue_terracotta", builder()));
+    public static final Item YELLOW_TERRACOTTA = register(new Item("yellow_terracotta", builder()));
+    public static final Item LIME_TERRACOTTA = register(new Item("lime_terracotta", builder()));
+    public static final Item PINK_TERRACOTTA = register(new Item("pink_terracotta", builder()));
+    public static final Item GRAY_TERRACOTTA = register(new Item("gray_terracotta", builder()));
+    public static final Item LIGHT_GRAY_TERRACOTTA = register(new Item("light_gray_terracotta", builder()));
+    public static final Item CYAN_TERRACOTTA = register(new Item("cyan_terracotta", builder()));
+    public static final Item PURPLE_TERRACOTTA = register(new Item("purple_terracotta", builder()));
+    public static final Item BLUE_TERRACOTTA = register(new Item("blue_terracotta", builder()));
+    public static final Item BROWN_TERRACOTTA = register(new Item("brown_terracotta", builder()));
+    public static final Item GREEN_TERRACOTTA = register(new Item("green_terracotta", builder()));
+    public static final Item RED_TERRACOTTA = register(new Item("red_terracotta", builder()));
+    public static final Item BLACK_TERRACOTTA = register(new Item("black_terracotta", builder()));
+    public static final Item BARRIER = register(new Item("barrier", builder()));
+    public static final Item LIGHT = register(new Item("light", builder()));
+    public static final Item HAY_BLOCK = register(new Item("hay_block", builder()));
+    public static final Item WHITE_CARPET = register(new Item("white_carpet", builder()));
+    public static final Item ORANGE_CARPET = register(new Item("orange_carpet", builder()));
+    public static final Item MAGENTA_CARPET = register(new Item("magenta_carpet", builder()));
+    public static final Item LIGHT_BLUE_CARPET = register(new Item("light_blue_carpet", builder()));
+    public static final Item YELLOW_CARPET = register(new Item("yellow_carpet", builder()));
+    public static final Item LIME_CARPET = register(new Item("lime_carpet", builder()));
+    public static final Item PINK_CARPET = register(new Item("pink_carpet", builder()));
+    public static final Item GRAY_CARPET = register(new Item("gray_carpet", builder()));
+    public static final Item LIGHT_GRAY_CARPET = register(new Item("light_gray_carpet", builder()));
+    public static final Item CYAN_CARPET = register(new Item("cyan_carpet", builder()));
+    public static final Item PURPLE_CARPET = register(new Item("purple_carpet", builder()));
+    public static final Item BLUE_CARPET = register(new Item("blue_carpet", builder()));
+    public static final Item BROWN_CARPET = register(new Item("brown_carpet", builder()));
+    public static final Item GREEN_CARPET = register(new Item("green_carpet", builder()));
+    public static final Item RED_CARPET = register(new Item("red_carpet", builder()));
+    public static final Item BLACK_CARPET = register(new Item("black_carpet", builder()));
+    public static final Item TERRACOTTA = register(new Item("terracotta", builder()));
+    public static final Item PACKED_ICE = register(new Item("packed_ice", builder()));
+    public static final Item DIRT_PATH = register(new Item("dirt_path", builder()));
+    public static final Item SUNFLOWER = register(new Item("sunflower", builder()));
+    public static final Item LILAC = register(new Item("lilac", builder()));
+    public static final Item ROSE_BUSH = register(new Item("rose_bush", builder()));
+    public static final Item PEONY = register(new Item("peony", builder()));
+    public static final Item TALL_GRASS = register(new Item("tall_grass", builder()));
+    public static final Item LARGE_FERN = register(new Item("large_fern", builder()));
+    public static final Item WHITE_STAINED_GLASS = register(new Item("white_stained_glass", builder()));
+    public static final Item ORANGE_STAINED_GLASS = register(new Item("orange_stained_glass", builder()));
+    public static final Item MAGENTA_STAINED_GLASS = register(new Item("magenta_stained_glass", builder()));
+    public static final Item LIGHT_BLUE_STAINED_GLASS = register(new Item("light_blue_stained_glass", builder()));
+    public static final Item YELLOW_STAINED_GLASS = register(new Item("yellow_stained_glass", builder()));
+    public static final Item LIME_STAINED_GLASS = register(new Item("lime_stained_glass", builder()));
+    public static final Item PINK_STAINED_GLASS = register(new Item("pink_stained_glass", builder()));
+    public static final Item GRAY_STAINED_GLASS = register(new Item("gray_stained_glass", builder()));
+    public static final Item LIGHT_GRAY_STAINED_GLASS = register(new Item("light_gray_stained_glass", builder()));
+    public static final Item CYAN_STAINED_GLASS = register(new Item("cyan_stained_glass", builder()));
+    public static final Item PURPLE_STAINED_GLASS = register(new Item("purple_stained_glass", builder()));
+    public static final Item BLUE_STAINED_GLASS = register(new Item("blue_stained_glass", builder()));
+    public static final Item BROWN_STAINED_GLASS = register(new Item("brown_stained_glass", builder()));
+    public static final Item GREEN_STAINED_GLASS = register(new Item("green_stained_glass", builder()));
+    public static final Item RED_STAINED_GLASS = register(new Item("red_stained_glass", builder()));
+    public static final Item BLACK_STAINED_GLASS = register(new Item("black_stained_glass", builder()));
+    public static final Item WHITE_STAINED_GLASS_PANE = register(new Item("white_stained_glass_pane", builder()));
+    public static final Item ORANGE_STAINED_GLASS_PANE = register(new Item("orange_stained_glass_pane", builder()));
+    public static final Item MAGENTA_STAINED_GLASS_PANE = register(new Item("magenta_stained_glass_pane", builder()));
+    public static final Item LIGHT_BLUE_STAINED_GLASS_PANE = register(new Item("light_blue_stained_glass_pane", builder()));
+    public static final Item YELLOW_STAINED_GLASS_PANE = register(new Item("yellow_stained_glass_pane", builder()));
+    public static final Item LIME_STAINED_GLASS_PANE = register(new Item("lime_stained_glass_pane", builder()));
+    public static final Item PINK_STAINED_GLASS_PANE = register(new Item("pink_stained_glass_pane", builder()));
+    public static final Item GRAY_STAINED_GLASS_PANE = register(new Item("gray_stained_glass_pane", builder()));
+    public static final Item LIGHT_GRAY_STAINED_GLASS_PANE = register(new Item("light_gray_stained_glass_pane", builder()));
+    public static final Item CYAN_STAINED_GLASS_PANE = register(new Item("cyan_stained_glass_pane", builder()));
+    public static final Item PURPLE_STAINED_GLASS_PANE = register(new Item("purple_stained_glass_pane", builder()));
+    public static final Item BLUE_STAINED_GLASS_PANE = register(new Item("blue_stained_glass_pane", builder()));
+    public static final Item BROWN_STAINED_GLASS_PANE = register(new Item("brown_stained_glass_pane", builder()));
+    public static final Item GREEN_STAINED_GLASS_PANE = register(new Item("green_stained_glass_pane", builder()));
+    public static final Item RED_STAINED_GLASS_PANE = register(new Item("red_stained_glass_pane", builder()));
+    public static final Item BLACK_STAINED_GLASS_PANE = register(new Item("black_stained_glass_pane", builder()));
+    public static final Item PRISMARINE = register(new Item("prismarine", builder()));
+    public static final Item PRISMARINE_BRICKS = register(new Item("prismarine_bricks", builder()));
+    public static final Item DARK_PRISMARINE = register(new Item("dark_prismarine", builder()));
+    public static final Item PRISMARINE_STAIRS = register(new Item("prismarine_stairs", builder()));
+    public static final Item PRISMARINE_BRICK_STAIRS = register(new Item("prismarine_brick_stairs", builder()));
+    public static final Item DARK_PRISMARINE_STAIRS = register(new Item("dark_prismarine_stairs", builder()));
+    public static final Item SEA_LANTERN = register(new Item("sea_lantern", builder()));
+    public static final Item RED_SANDSTONE = register(new Item("red_sandstone", builder()));
+    public static final Item CHISELED_RED_SANDSTONE = register(new Item("chiseled_red_sandstone", builder()));
+    public static final Item CUT_RED_SANDSTONE = register(new Item("cut_red_sandstone", builder()));
+    public static final Item RED_SANDSTONE_STAIRS = register(new Item("red_sandstone_stairs", builder()));
+    public static final Item REPEATING_COMMAND_BLOCK = register(new Item("repeating_command_block", builder()));
+    public static final Item CHAIN_COMMAND_BLOCK = register(new Item("chain_command_block", builder()));
+    public static final Item MAGMA_BLOCK = register(new Item("magma_block", builder()));
+    public static final Item NETHER_WART_BLOCK = register(new Item("nether_wart_block", builder()));
+    public static final Item WARPED_WART_BLOCK = register(new Item("warped_wart_block", builder()));
+    public static final Item RED_NETHER_BRICKS = register(new Item("red_nether_bricks", builder()));
+    public static final Item BONE_BLOCK = register(new Item("bone_block", builder()));
+    public static final Item STRUCTURE_VOID = register(new Item("structure_void", builder()));
+    public static final Item SHULKER_BOX = register(new Item("shulker_box", builder().stackSize(1)));
+    public static final Item WHITE_SHULKER_BOX = register(new Item("white_shulker_box", builder().stackSize(1)));
+    public static final Item ORANGE_SHULKER_BOX = register(new Item("orange_shulker_box", builder().stackSize(1)));
+    public static final Item MAGENTA_SHULKER_BOX = register(new Item("magenta_shulker_box", builder().stackSize(1)));
+    public static final Item LIGHT_BLUE_SHULKER_BOX = register(new Item("light_blue_shulker_box", builder().stackSize(1)));
+    public static final Item YELLOW_SHULKER_BOX = register(new Item("yellow_shulker_box", builder().stackSize(1)));
+    public static final Item LIME_SHULKER_BOX = register(new Item("lime_shulker_box", builder().stackSize(1)));
+    public static final Item PINK_SHULKER_BOX = register(new Item("pink_shulker_box", builder().stackSize(1)));
+    public static final Item GRAY_SHULKER_BOX = register(new Item("gray_shulker_box", builder().stackSize(1)));
+    public static final Item LIGHT_GRAY_SHULKER_BOX = register(new Item("light_gray_shulker_box", builder().stackSize(1)));
+    public static final Item CYAN_SHULKER_BOX = register(new Item("cyan_shulker_box", builder().stackSize(1)));
+    public static final Item PURPLE_SHULKER_BOX = register(new Item("purple_shulker_box", builder().stackSize(1)));
+    public static final Item BLUE_SHULKER_BOX = register(new Item("blue_shulker_box", builder().stackSize(1)));
+    public static final Item BROWN_SHULKER_BOX = register(new Item("brown_shulker_box", builder().stackSize(1)));
+    public static final Item GREEN_SHULKER_BOX = register(new Item("green_shulker_box", builder().stackSize(1)));
+    public static final Item RED_SHULKER_BOX = register(new Item("red_shulker_box", builder().stackSize(1)));
+    public static final Item BLACK_SHULKER_BOX = register(new Item("black_shulker_box", builder().stackSize(1)));
+    public static final Item WHITE_GLAZED_TERRACOTTA = register(new Item("white_glazed_terracotta", builder()));
+    public static final Item ORANGE_GLAZED_TERRACOTTA = register(new Item("orange_glazed_terracotta", builder()));
+    public static final Item MAGENTA_GLAZED_TERRACOTTA = register(new Item("magenta_glazed_terracotta", builder()));
+    public static final Item LIGHT_BLUE_GLAZED_TERRACOTTA = register(new Item("light_blue_glazed_terracotta", builder()));
+    public static final Item YELLOW_GLAZED_TERRACOTTA = register(new Item("yellow_glazed_terracotta", builder()));
+    public static final Item LIME_GLAZED_TERRACOTTA = register(new Item("lime_glazed_terracotta", builder()));
+    public static final Item PINK_GLAZED_TERRACOTTA = register(new Item("pink_glazed_terracotta", builder()));
+    public static final Item GRAY_GLAZED_TERRACOTTA = register(new Item("gray_glazed_terracotta", builder()));
+    public static final Item LIGHT_GRAY_GLAZED_TERRACOTTA = register(new Item("light_gray_glazed_terracotta", builder()));
+    public static final Item CYAN_GLAZED_TERRACOTTA = register(new Item("cyan_glazed_terracotta", builder()));
+    public static final Item PURPLE_GLAZED_TERRACOTTA = register(new Item("purple_glazed_terracotta", builder()));
+    public static final Item BLUE_GLAZED_TERRACOTTA = register(new Item("blue_glazed_terracotta", builder()));
+    public static final Item BROWN_GLAZED_TERRACOTTA = register(new Item("brown_glazed_terracotta", builder()));
+    public static final Item GREEN_GLAZED_TERRACOTTA = register(new Item("green_glazed_terracotta", builder()));
+    public static final Item RED_GLAZED_TERRACOTTA = register(new Item("red_glazed_terracotta", builder()));
+    public static final Item BLACK_GLAZED_TERRACOTTA = register(new Item("black_glazed_terracotta", builder()));
+    public static final Item WHITE_CONCRETE = register(new Item("white_concrete", builder()));
+    public static final Item ORANGE_CONCRETE = register(new Item("orange_concrete", builder()));
+    public static final Item MAGENTA_CONCRETE = register(new Item("magenta_concrete", builder()));
+    public static final Item LIGHT_BLUE_CONCRETE = register(new Item("light_blue_concrete", builder()));
+    public static final Item YELLOW_CONCRETE = register(new Item("yellow_concrete", builder()));
+    public static final Item LIME_CONCRETE = register(new Item("lime_concrete", builder()));
+    public static final Item PINK_CONCRETE = register(new Item("pink_concrete", builder()));
+    public static final Item GRAY_CONCRETE = register(new Item("gray_concrete", builder()));
+    public static final Item LIGHT_GRAY_CONCRETE = register(new Item("light_gray_concrete", builder()));
+    public static final Item CYAN_CONCRETE = register(new Item("cyan_concrete", builder()));
+    public static final Item PURPLE_CONCRETE = register(new Item("purple_concrete", builder()));
+    public static final Item BLUE_CONCRETE = register(new Item("blue_concrete", builder()));
+    public static final Item BROWN_CONCRETE = register(new Item("brown_concrete", builder()));
+    public static final Item GREEN_CONCRETE = register(new Item("green_concrete", builder()));
+    public static final Item RED_CONCRETE = register(new Item("red_concrete", builder()));
+    public static final Item BLACK_CONCRETE = register(new Item("black_concrete", builder()));
+    public static final Item WHITE_CONCRETE_POWDER = register(new Item("white_concrete_powder", builder()));
+    public static final Item ORANGE_CONCRETE_POWDER = register(new Item("orange_concrete_powder", builder()));
+    public static final Item MAGENTA_CONCRETE_POWDER = register(new Item("magenta_concrete_powder", builder()));
+    public static final Item LIGHT_BLUE_CONCRETE_POWDER = register(new Item("light_blue_concrete_powder", builder()));
+    public static final Item YELLOW_CONCRETE_POWDER = register(new Item("yellow_concrete_powder", builder()));
+    public static final Item LIME_CONCRETE_POWDER = register(new Item("lime_concrete_powder", builder()));
+    public static final Item PINK_CONCRETE_POWDER = register(new Item("pink_concrete_powder", builder()));
+    public static final Item GRAY_CONCRETE_POWDER = register(new Item("gray_concrete_powder", builder()));
+    public static final Item LIGHT_GRAY_CONCRETE_POWDER = register(new Item("light_gray_concrete_powder", builder()));
+    public static final Item CYAN_CONCRETE_POWDER = register(new Item("cyan_concrete_powder", builder()));
+    public static final Item PURPLE_CONCRETE_POWDER = register(new Item("purple_concrete_powder", builder()));
+    public static final Item BLUE_CONCRETE_POWDER = register(new Item("blue_concrete_powder", builder()));
+    public static final Item BROWN_CONCRETE_POWDER = register(new Item("brown_concrete_powder", builder()));
+    public static final Item GREEN_CONCRETE_POWDER = register(new Item("green_concrete_powder", builder()));
+    public static final Item RED_CONCRETE_POWDER = register(new Item("red_concrete_powder", builder()));
+    public static final Item BLACK_CONCRETE_POWDER = register(new Item("black_concrete_powder", builder()));
+    public static final Item TURTLE_EGG = register(new Item("turtle_egg", builder()));
+    public static final Item DEAD_TUBE_CORAL_BLOCK = register(new Item("dead_tube_coral_block", builder()));
+    public static final Item DEAD_BRAIN_CORAL_BLOCK = register(new Item("dead_brain_coral_block", builder()));
+    public static final Item DEAD_BUBBLE_CORAL_BLOCK = register(new Item("dead_bubble_coral_block", builder()));
+    public static final Item DEAD_FIRE_CORAL_BLOCK = register(new Item("dead_fire_coral_block", builder()));
+    public static final Item DEAD_HORN_CORAL_BLOCK = register(new Item("dead_horn_coral_block", builder()));
+    public static final Item TUBE_CORAL_BLOCK = register(new Item("tube_coral_block", builder()));
+    public static final Item BRAIN_CORAL_BLOCK = register(new Item("brain_coral_block", builder()));
+    public static final Item BUBBLE_CORAL_BLOCK = register(new Item("bubble_coral_block", builder()));
+    public static final Item FIRE_CORAL_BLOCK = register(new Item("fire_coral_block", builder()));
+    public static final Item HORN_CORAL_BLOCK = register(new Item("horn_coral_block", builder()));
+    public static final Item TUBE_CORAL = register(new Item("tube_coral", builder()));
+    public static final Item BRAIN_CORAL = register(new Item("brain_coral", builder()));
+    public static final Item BUBBLE_CORAL = register(new Item("bubble_coral", builder()));
+    public static final Item FIRE_CORAL = register(new Item("fire_coral", builder()));
+    public static final Item HORN_CORAL = register(new Item("horn_coral", builder()));
+    public static final Item DEAD_BRAIN_CORAL = register(new Item("dead_brain_coral", builder()));
+    public static final Item DEAD_BUBBLE_CORAL = register(new Item("dead_bubble_coral", builder()));
+    public static final Item DEAD_FIRE_CORAL = register(new Item("dead_fire_coral", builder()));
+    public static final Item DEAD_HORN_CORAL = register(new Item("dead_horn_coral", builder()));
+    public static final Item DEAD_TUBE_CORAL = register(new Item("dead_tube_coral", builder()));
+    public static final Item TUBE_CORAL_FAN = register(new Item("tube_coral_fan", builder()));
+    public static final Item BRAIN_CORAL_FAN = register(new Item("brain_coral_fan", builder()));
+    public static final Item BUBBLE_CORAL_FAN = register(new Item("bubble_coral_fan", builder()));
+    public static final Item FIRE_CORAL_FAN = register(new Item("fire_coral_fan", builder()));
+    public static final Item HORN_CORAL_FAN = register(new Item("horn_coral_fan", builder()));
+    public static final Item DEAD_TUBE_CORAL_FAN = register(new Item("dead_tube_coral_fan", builder()));
+    public static final Item DEAD_BRAIN_CORAL_FAN = register(new Item("dead_brain_coral_fan", builder()));
+    public static final Item DEAD_BUBBLE_CORAL_FAN = register(new Item("dead_bubble_coral_fan", builder()));
+    public static final Item DEAD_FIRE_CORAL_FAN = register(new Item("dead_fire_coral_fan", builder()));
+    public static final Item DEAD_HORN_CORAL_FAN = register(new Item("dead_horn_coral_fan", builder()));
+    public static final Item BLUE_ICE = register(new Item("blue_ice", builder()));
+    public static final Item CONDUIT = register(new Item("conduit", builder()));
+    public static final Item POLISHED_GRANITE_STAIRS = register(new Item("polished_granite_stairs", builder()));
+    public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new Item("smooth_red_sandstone_stairs", builder()));
+    public static final Item MOSSY_STONE_BRICK_STAIRS = register(new Item("mossy_stone_brick_stairs", builder()));
+    public static final Item POLISHED_DIORITE_STAIRS = register(new Item("polished_diorite_stairs", builder()));
+    public static final Item MOSSY_COBBLESTONE_STAIRS = register(new Item("mossy_cobblestone_stairs", builder()));
+    public static final Item END_STONE_BRICK_STAIRS = register(new Item("end_stone_brick_stairs", builder()));
+    public static final Item STONE_STAIRS = register(new Item("stone_stairs", builder()));
+    public static final Item SMOOTH_SANDSTONE_STAIRS = register(new Item("smooth_sandstone_stairs", builder()));
+    public static final Item SMOOTH_QUARTZ_STAIRS = register(new Item("smooth_quartz_stairs", builder()));
+    public static final Item GRANITE_STAIRS = register(new Item("granite_stairs", builder()));
+    public static final Item ANDESITE_STAIRS = register(new Item("andesite_stairs", builder()));
+    public static final Item RED_NETHER_BRICK_STAIRS = register(new Item("red_nether_brick_stairs", builder()));
+    public static final Item POLISHED_ANDESITE_STAIRS = register(new Item("polished_andesite_stairs", builder()));
+    public static final Item DIORITE_STAIRS = register(new Item("diorite_stairs", builder()));
+    public static final Item COBBLED_DEEPSLATE_STAIRS = register(new Item("cobbled_deepslate_stairs", builder()));
+    public static final Item POLISHED_DEEPSLATE_STAIRS = register(new Item("polished_deepslate_stairs", builder()));
+    public static final Item DEEPSLATE_BRICK_STAIRS = register(new Item("deepslate_brick_stairs", builder()));
+    public static final Item DEEPSLATE_TILE_STAIRS = register(new Item("deepslate_tile_stairs", builder()));
+    public static final Item POLISHED_GRANITE_SLAB = register(new Item("polished_granite_slab", builder()));
+    public static final Item SMOOTH_RED_SANDSTONE_SLAB = register(new Item("smooth_red_sandstone_slab", builder()));
+    public static final Item MOSSY_STONE_BRICK_SLAB = register(new Item("mossy_stone_brick_slab", builder()));
+    public static final Item POLISHED_DIORITE_SLAB = register(new Item("polished_diorite_slab", builder()));
+    public static final Item MOSSY_COBBLESTONE_SLAB = register(new Item("mossy_cobblestone_slab", builder()));
+    public static final Item END_STONE_BRICK_SLAB = register(new Item("end_stone_brick_slab", builder()));
+    public static final Item SMOOTH_SANDSTONE_SLAB = register(new Item("smooth_sandstone_slab", builder()));
+    public static final Item SMOOTH_QUARTZ_SLAB = register(new Item("smooth_quartz_slab", builder()));
+    public static final Item GRANITE_SLAB = register(new Item("granite_slab", builder()));
+    public static final Item ANDESITE_SLAB = register(new Item("andesite_slab", builder()));
+    public static final Item RED_NETHER_BRICK_SLAB = register(new Item("red_nether_brick_slab", builder()));
+    public static final Item POLISHED_ANDESITE_SLAB = register(new Item("polished_andesite_slab", builder()));
+    public static final Item DIORITE_SLAB = register(new Item("diorite_slab", builder()));
+    public static final Item COBBLED_DEEPSLATE_SLAB = register(new Item("cobbled_deepslate_slab", builder()));
+    public static final Item POLISHED_DEEPSLATE_SLAB = register(new Item("polished_deepslate_slab", builder()));
+    public static final Item DEEPSLATE_BRICK_SLAB = register(new Item("deepslate_brick_slab", builder()));
+    public static final Item DEEPSLATE_TILE_SLAB = register(new Item("deepslate_tile_slab", builder()));
+    public static final Item SCAFFOLDING = register(new Item("scaffolding", builder()));
+    public static final Item REDSTONE = register(new Item("redstone", builder()));
+    public static final Item REDSTONE_TORCH = register(new Item("redstone_torch", builder()));
+    public static final Item REDSTONE_BLOCK = register(new Item("redstone_block", builder()));
+    public static final Item REPEATER = register(new Item("repeater", builder()));
+    public static final Item COMPARATOR = register(new Item("comparator", builder()));
+    public static final Item PISTON = register(new Item("piston", builder()));
+    public static final Item STICKY_PISTON = register(new Item("sticky_piston", builder()));
+    public static final Item SLIME_BLOCK = register(new Item("slime_block", builder()));
+    public static final Item HONEY_BLOCK = register(new Item("honey_block", builder()));
+    public static final Item OBSERVER = register(new Item("observer", builder()));
+    public static final Item HOPPER = register(new Item("hopper", builder()));
+    public static final Item DISPENSER = register(new Item("dispenser", builder()));
+    public static final Item DROPPER = register(new Item("dropper", builder()));
+    public static final Item LECTERN = register(new Item("lectern", builder()));
+    public static final Item TARGET = register(new Item("target", builder()));
+    public static final Item LEVER = register(new Item("lever", builder()));
+    public static final Item LIGHTNING_ROD = register(new Item("lightning_rod", builder()));
+    public static final Item DAYLIGHT_DETECTOR = register(new Item("daylight_detector", builder()));
+    public static final Item SCULK_SENSOR = register(new Item("sculk_sensor", builder()));
+    public static final Item TRIPWIRE_HOOK = register(new Item("tripwire_hook", builder()));
+    public static final Item TRAPPED_CHEST = register(new Item("trapped_chest", builder()));
+    public static final Item TNT = register(new Item("tnt", builder()));
+    public static final Item REDSTONE_LAMP = register(new Item("redstone_lamp", builder()));
+    public static final Item NOTE_BLOCK = register(new Item("note_block", builder()));
+    public static final Item STONE_BUTTON = register(new Item("stone_button", builder()));
+    public static final Item POLISHED_BLACKSTONE_BUTTON = register(new Item("polished_blackstone_button", builder()));
+    public static final Item OAK_BUTTON = register(new Item("oak_button", builder()));
+    public static final Item SPRUCE_BUTTON = register(new Item("spruce_button", builder()));
+    public static final Item BIRCH_BUTTON = register(new Item("birch_button", builder()));
+    public static final Item JUNGLE_BUTTON = register(new Item("jungle_button", builder()));
+    public static final Item ACACIA_BUTTON = register(new Item("acacia_button", builder()));
+    public static final Item DARK_OAK_BUTTON = register(new Item("dark_oak_button", builder()));
+    public static final Item MANGROVE_BUTTON = register(new Item("mangrove_button", builder()));
+    public static final Item BAMBOO_BUTTON = register(new Item("bamboo_button", builder()));
+    public static final Item CRIMSON_BUTTON = register(new Item("crimson_button", builder()));
+    public static final Item WARPED_BUTTON = register(new Item("warped_button", builder()));
+    public static final Item STONE_PRESSURE_PLATE = register(new Item("stone_pressure_plate", builder()));
+    public static final Item POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Item("polished_blackstone_pressure_plate", builder()));
+    public static final Item LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Item("light_weighted_pressure_plate", builder()));
+    public static final Item HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Item("heavy_weighted_pressure_plate", builder()));
+    public static final Item OAK_PRESSURE_PLATE = register(new Item("oak_pressure_plate", builder()));
+    public static final Item SPRUCE_PRESSURE_PLATE = register(new Item("spruce_pressure_plate", builder()));
+    public static final Item BIRCH_PRESSURE_PLATE = register(new Item("birch_pressure_plate", builder()));
+    public static final Item JUNGLE_PRESSURE_PLATE = register(new Item("jungle_pressure_plate", builder()));
+    public static final Item ACACIA_PRESSURE_PLATE = register(new Item("acacia_pressure_plate", builder()));
+    public static final Item DARK_OAK_PRESSURE_PLATE = register(new Item("dark_oak_pressure_plate", builder()));
+    public static final Item MANGROVE_PRESSURE_PLATE = register(new Item("mangrove_pressure_plate", builder()));
+    public static final Item BAMBOO_PRESSURE_PLATE = register(new Item("bamboo_pressure_plate", builder()));
+    public static final Item CRIMSON_PRESSURE_PLATE = register(new Item("crimson_pressure_plate", builder()));
+    public static final Item WARPED_PRESSURE_PLATE = register(new Item("warped_pressure_plate", builder()));
+    public static final Item IRON_DOOR = register(new Item("iron_door", builder()));
+    public static final Item OAK_DOOR = register(new Item("oak_door", builder()));
+    public static final Item SPRUCE_DOOR = register(new Item("spruce_door", builder()));
+    public static final Item BIRCH_DOOR = register(new Item("birch_door", builder()));
+    public static final Item JUNGLE_DOOR = register(new Item("jungle_door", builder()));
+    public static final Item ACACIA_DOOR = register(new Item("acacia_door", builder()));
+    public static final Item DARK_OAK_DOOR = register(new Item("dark_oak_door", builder()));
+    public static final Item MANGROVE_DOOR = register(new Item("mangrove_door", builder()));
+    public static final Item BAMBOO_DOOR = register(new Item("bamboo_door", builder()));
+    public static final Item CRIMSON_DOOR = register(new Item("crimson_door", builder()));
+    public static final Item WARPED_DOOR = register(new Item("warped_door", builder()));
+    public static final Item IRON_TRAPDOOR = register(new Item("iron_trapdoor", builder()));
+    public static final Item OAK_TRAPDOOR = register(new Item("oak_trapdoor", builder()));
+    public static final Item SPRUCE_TRAPDOOR = register(new Item("spruce_trapdoor", builder()));
+    public static final Item BIRCH_TRAPDOOR = register(new Item("birch_trapdoor", builder()));
+    public static final Item JUNGLE_TRAPDOOR = register(new Item("jungle_trapdoor", builder()));
+    public static final Item ACACIA_TRAPDOOR = register(new Item("acacia_trapdoor", builder()));
+    public static final Item DARK_OAK_TRAPDOOR = register(new Item("dark_oak_trapdoor", builder()));
+    public static final Item MANGROVE_TRAPDOOR = register(new Item("mangrove_trapdoor", builder()));
+    public static final Item BAMBOO_TRAPDOOR = register(new Item("bamboo_trapdoor", builder()));
+    public static final Item CRIMSON_TRAPDOOR = register(new Item("crimson_trapdoor", builder()));
+    public static final Item WARPED_TRAPDOOR = register(new Item("warped_trapdoor", builder()));
+    public static final Item OAK_FENCE_GATE = register(new Item("oak_fence_gate", builder()));
+    public static final Item SPRUCE_FENCE_GATE = register(new Item("spruce_fence_gate", builder()));
+    public static final Item BIRCH_FENCE_GATE = register(new Item("birch_fence_gate", builder()));
+    public static final Item JUNGLE_FENCE_GATE = register(new Item("jungle_fence_gate", builder()));
+    public static final Item ACACIA_FENCE_GATE = register(new Item("acacia_fence_gate", builder()));
+    public static final Item DARK_OAK_FENCE_GATE = register(new Item("dark_oak_fence_gate", builder()));
+    public static final Item MANGROVE_FENCE_GATE = register(new Item("mangrove_fence_gate", builder()));
+    public static final Item BAMBOO_FENCE_GATE = register(new Item("bamboo_fence_gate", builder()));
+    public static final Item CRIMSON_FENCE_GATE = register(new Item("crimson_fence_gate", builder()));
+    public static final Item WARPED_FENCE_GATE = register(new Item("warped_fence_gate", builder()));
+    public static final Item POWERED_RAIL = register(new Item("powered_rail", builder()));
+    public static final Item DETECTOR_RAIL = register(new Item("detector_rail", builder()));
+    public static final Item RAIL = register(new Item("rail", builder()));
+    public static final Item ACTIVATOR_RAIL = register(new Item("activator_rail", builder()));
+    public static final Item SADDLE = register(new Item("saddle", builder().stackSize(1)));
+    public static final Item MINECART = register(new Item("minecart", builder().stackSize(1)));
+    public static final Item CHEST_MINECART = register(new Item("chest_minecart", builder().stackSize(1)));
+    public static final Item FURNACE_MINECART = register(new Item("furnace_minecart", builder().stackSize(1)));
+    public static final Item TNT_MINECART = register(new Item("tnt_minecart", builder().stackSize(1)));
+    public static final Item HOPPER_MINECART = register(new Item("hopper_minecart", builder().stackSize(1)));
+    public static final Item CARROT_ON_A_STICK = register(new Item("carrot_on_a_stick", builder().stackSize(1).maxDamage(25)));
+    public static final Item WARPED_FUNGUS_ON_A_STICK = register(new Item("warped_fungus_on_a_stick", builder().stackSize(1).maxDamage(100)));
+    public static final Item ELYTRA = register(new Item("elytra", builder().stackSize(1).maxDamage(432)));
+    public static final Item OAK_BOAT = register(new Item("oak_boat", builder().stackSize(1)));
+    public static final Item OAK_CHEST_BOAT = register(new Item("oak_chest_boat", builder().stackSize(1)));
+    public static final Item SPRUCE_BOAT = register(new Item("spruce_boat", builder().stackSize(1)));
+    public static final Item SPRUCE_CHEST_BOAT = register(new Item("spruce_chest_boat", builder().stackSize(1)));
+    public static final Item BIRCH_BOAT = register(new Item("birch_boat", builder().stackSize(1)));
+    public static final Item BIRCH_CHEST_BOAT = register(new Item("birch_chest_boat", builder().stackSize(1)));
+    public static final Item JUNGLE_BOAT = register(new Item("jungle_boat", builder().stackSize(1)));
+    public static final Item JUNGLE_CHEST_BOAT = register(new Item("jungle_chest_boat", builder().stackSize(1)));
+    public static final Item ACACIA_BOAT = register(new Item("acacia_boat", builder().stackSize(1)));
+    public static final Item ACACIA_CHEST_BOAT = register(new Item("acacia_chest_boat", builder().stackSize(1)));
+    public static final Item DARK_OAK_BOAT = register(new Item("dark_oak_boat", builder().stackSize(1)));
+    public static final Item DARK_OAK_CHEST_BOAT = register(new Item("dark_oak_chest_boat", builder().stackSize(1)));
+    public static final Item MANGROVE_BOAT = register(new Item("mangrove_boat", builder().stackSize(1)));
+    public static final Item MANGROVE_CHEST_BOAT = register(new Item("mangrove_chest_boat", builder().stackSize(1)));
+    public static final Item BAMBOO_RAFT = register(new Item("bamboo_raft", builder().stackSize(1)));
+    public static final Item BAMBOO_CHEST_RAFT = register(new Item("bamboo_chest_raft", builder().stackSize(1)));
+    public static final Item STRUCTURE_BLOCK = register(new Item("structure_block", builder()));
+    public static final Item JIGSAW = register(new Item("jigsaw", builder()));
+    public static final Item TURTLE_HELMET = register(new Item("turtle_helmet", builder().stackSize(1).maxDamage(275)));
+    public static final Item SCUTE = register(new Item("scute", builder()));
+    public static final Item FLINT_AND_STEEL = register(new Item("flint_and_steel", builder().stackSize(1).maxDamage(64)));
+    public static final Item APPLE = register(new Item("apple", builder()));
+    public static final Item BOW = register(new Item("bow", builder().stackSize(1).maxDamage(384)));
+    public static final ArrowItem ARROW = register(new ArrowItem("arrow", builder()));
+    public static final Item COAL = register(new Item("coal", builder()));
+    public static final Item CHARCOAL = register(new Item("charcoal", builder()));
+    public static final Item DIAMOND = register(new Item("diamond", builder()));
+    public static final Item EMERALD = register(new Item("emerald", builder()));
+    public static final Item LAPIS_LAZULI = register(new Item("lapis_lazuli", builder()));
+    public static final Item QUARTZ = register(new Item("quartz", builder()));
+    public static final Item AMETHYST_SHARD = register(new Item("amethyst_shard", builder()));
+    public static final Item RAW_IRON = register(new Item("raw_iron", builder()));
+    public static final Item IRON_INGOT = register(new Item("iron_ingot", builder()));
+    public static final Item RAW_COPPER = register(new Item("raw_copper", builder()));
+    public static final Item COPPER_INGOT = register(new Item("copper_ingot", builder()));
+    public static final Item RAW_GOLD = register(new Item("raw_gold", builder()));
+    public static final Item GOLD_INGOT = register(new Item("gold_ingot", builder()));
+    public static final Item NETHERITE_INGOT = register(new Item("netherite_ingot", builder()));
+    public static final Item NETHERITE_SCRAP = register(new Item("netherite_scrap", builder()));
+    public static final TieredItem WOODEN_SWORD = register(new TieredItem("wooden_sword", builder().stackSize(1).maxDamage(59)));
+    public static final TieredItem WOODEN_SHOVEL = register(new TieredItem("wooden_shovel", builder().stackSize(1).maxDamage(59)));
+    public static final TieredItem WOODEN_PICKAXE = register(new TieredItem("wooden_pickaxe", builder().stackSize(1).maxDamage(59)));
+    public static final TieredItem WOODEN_AXE = register(new TieredItem("wooden_axe", builder().stackSize(1).maxDamage(59)));
+    public static final TieredItem WOODEN_HOE = register(new TieredItem("wooden_hoe", builder().stackSize(1).maxDamage(59)));
+    public static final TieredItem STONE_SWORD = register(new TieredItem("stone_sword", builder().stackSize(1).maxDamage(131)));
+    public static final TieredItem STONE_SHOVEL = register(new TieredItem("stone_shovel", builder().stackSize(1).maxDamage(131)));
+    public static final TieredItem STONE_PICKAXE = register(new TieredItem("stone_pickaxe", builder().stackSize(1).maxDamage(131)));
+    public static final TieredItem STONE_AXE = register(new TieredItem("stone_axe", builder().stackSize(1).maxDamage(131)));
+    public static final TieredItem STONE_HOE = register(new TieredItem("stone_hoe", builder().stackSize(1).maxDamage(131)));
+    public static final TieredItem GOLDEN_SWORD = register(new TieredItem("golden_sword", builder().stackSize(1).maxDamage(32)));
+    public static final TieredItem GOLDEN_SHOVEL = register(new TieredItem("golden_shovel", builder().stackSize(1).maxDamage(32)));
+    public static final TieredItem GOLDEN_PICKAXE = register(new TieredItem("golden_pickaxe", builder().stackSize(1).maxDamage(32)));
+    public static final TieredItem GOLDEN_AXE = register(new TieredItem("golden_axe", builder().stackSize(1).maxDamage(32)));
+    public static final TieredItem GOLDEN_HOE = register(new TieredItem("golden_hoe", builder().stackSize(1).maxDamage(32)));
+    public static final TieredItem IRON_SWORD = register(new TieredItem("iron_sword", builder().stackSize(1).maxDamage(250)));
+    public static final TieredItem IRON_SHOVEL = register(new TieredItem("iron_shovel", builder().stackSize(1).maxDamage(250)));
+    public static final TieredItem IRON_PICKAXE = register(new TieredItem("iron_pickaxe", builder().stackSize(1).maxDamage(250)));
+    public static final TieredItem IRON_AXE = register(new TieredItem("iron_axe", builder().stackSize(1).maxDamage(250)));
+    public static final TieredItem IRON_HOE = register(new TieredItem("iron_hoe", builder().stackSize(1).maxDamage(250)));
+    public static final TieredItem DIAMOND_SWORD = register(new TieredItem("diamond_sword", builder().stackSize(1).maxDamage(1561)));
+    public static final TieredItem DIAMOND_SHOVEL = register(new TieredItem("diamond_shovel", builder().stackSize(1).maxDamage(1561)));
+    public static final TieredItem DIAMOND_PICKAXE = register(new TieredItem("diamond_pickaxe", builder().stackSize(1).maxDamage(1561)));
+    public static final TieredItem DIAMOND_AXE = register(new TieredItem("diamond_axe", builder().stackSize(1).maxDamage(1561)));
+    public static final TieredItem DIAMOND_HOE = register(new TieredItem("diamond_hoe", builder().stackSize(1).maxDamage(1561)));
+    public static final TieredItem NETHERITE_SWORD = register(new TieredItem("netherite_sword", builder().stackSize(1).maxDamage(2031)));
+    public static final TieredItem NETHERITE_SHOVEL = register(new TieredItem("netherite_shovel", builder().stackSize(1).maxDamage(2031)));
+    public static final TieredItem NETHERITE_PICKAXE = register(new TieredItem("netherite_pickaxe", builder().stackSize(1).maxDamage(2031)));
+    public static final TieredItem NETHERITE_AXE = register(new TieredItem("netherite_axe", builder().stackSize(1).maxDamage(2031)));
+    public static final TieredItem NETHERITE_HOE = register(new TieredItem("netherite_hoe", builder().stackSize(1).maxDamage(2031)));
+    public static final Item STICK = register(new Item("stick", builder()));
+    public static final Item BOWL = register(new Item("bowl", builder()));
+    public static final Item MUSHROOM_STEW = register(new Item("mushroom_stew", builder().stackSize(1)));
+    public static final Item STRING = register(new Item("string", builder()));
+    public static final Item FEATHER = register(new Item("feather", builder()));
+    public static final Item GUNPOWDER = register(new Item("gunpowder", builder()));
+    public static final Item WHEAT_SEEDS = register(new Item("wheat_seeds", builder()));
+    public static final Item WHEAT = register(new Item("wheat", builder()));
+    public static final Item BREAD = register(new Item("bread", builder()));
+    public static final Item LEATHER_HELMET = register(new Item("leather_helmet", builder().stackSize(1).maxDamage(55)));
+    public static final Item LEATHER_CHESTPLATE = register(new Item("leather_chestplate", builder().stackSize(1).maxDamage(80)));
+    public static final Item LEATHER_LEGGINGS = register(new Item("leather_leggings", builder().stackSize(1).maxDamage(75)));
+    public static final Item LEATHER_BOOTS = register(new Item("leather_boots", builder().stackSize(1).maxDamage(65)));
+    public static final Item CHAINMAIL_HELMET = register(new Item("chainmail_helmet", builder().stackSize(1).maxDamage(165)));
+    public static final Item CHAINMAIL_CHESTPLATE = register(new Item("chainmail_chestplate", builder().stackSize(1).maxDamage(240)));
+    public static final Item CHAINMAIL_LEGGINGS = register(new Item("chainmail_leggings", builder().stackSize(1).maxDamage(225)));
+    public static final Item CHAINMAIL_BOOTS = register(new Item("chainmail_boots", builder().stackSize(1).maxDamage(195)));
+    public static final Item IRON_HELMET = register(new Item("iron_helmet", builder().stackSize(1).maxDamage(165)));
+    public static final Item IRON_CHESTPLATE = register(new Item("iron_chestplate", builder().stackSize(1).maxDamage(240)));
+    public static final Item IRON_LEGGINGS = register(new Item("iron_leggings", builder().stackSize(1).maxDamage(225)));
+    public static final Item IRON_BOOTS = register(new Item("iron_boots", builder().stackSize(1).maxDamage(195)));
+    public static final Item DIAMOND_HELMET = register(new Item("diamond_helmet", builder().stackSize(1).maxDamage(363)));
+    public static final Item DIAMOND_CHESTPLATE = register(new Item("diamond_chestplate", builder().stackSize(1).maxDamage(528)));
+    public static final Item DIAMOND_LEGGINGS = register(new Item("diamond_leggings", builder().stackSize(1).maxDamage(495)));
+    public static final Item DIAMOND_BOOTS = register(new Item("diamond_boots", builder().stackSize(1).maxDamage(429)));
+    public static final Item GOLDEN_HELMET = register(new Item("golden_helmet", builder().stackSize(1).maxDamage(77)));
+    public static final Item GOLDEN_CHESTPLATE = register(new Item("golden_chestplate", builder().stackSize(1).maxDamage(112)));
+    public static final Item GOLDEN_LEGGINGS = register(new Item("golden_leggings", builder().stackSize(1).maxDamage(105)));
+    public static final Item GOLDEN_BOOTS = register(new Item("golden_boots", builder().stackSize(1).maxDamage(91)));
+    public static final Item NETHERITE_HELMET = register(new Item("netherite_helmet", builder().stackSize(1).maxDamage(407)));
+    public static final Item NETHERITE_CHESTPLATE = register(new Item("netherite_chestplate", builder().stackSize(1).maxDamage(592)));
+    public static final Item NETHERITE_LEGGINGS = register(new Item("netherite_leggings", builder().stackSize(1).maxDamage(555)));
+    public static final Item NETHERITE_BOOTS = register(new Item("netherite_boots", builder().stackSize(1).maxDamage(481)));
+    public static final Item FLINT = register(new Item("flint", builder()));
+    public static final Item PORKCHOP = register(new Item("porkchop", builder()));
+    public static final Item COOKED_PORKCHOP = register(new Item("cooked_porkchop", builder()));
+    public static final Item PAINTING = register(new Item("painting", builder()));
+    public static final Item GOLDEN_APPLE = register(new Item("golden_apple", builder()));
+    public static final Item ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder()));
+    public static final Item OAK_SIGN = register(new Item("oak_sign", builder().stackSize(16)));
+    public static final Item SPRUCE_SIGN = register(new Item("spruce_sign", builder().stackSize(16)));
+    public static final Item BIRCH_SIGN = register(new Item("birch_sign", builder().stackSize(16)));
+    public static final Item JUNGLE_SIGN = register(new Item("jungle_sign", builder().stackSize(16)));
+    public static final Item ACACIA_SIGN = register(new Item("acacia_sign", builder().stackSize(16)));
+    public static final Item DARK_OAK_SIGN = register(new Item("dark_oak_sign", builder().stackSize(16)));
+    public static final Item MANGROVE_SIGN = register(new Item("mangrove_sign", builder().stackSize(16)));
+    public static final Item BAMBOO_SIGN = register(new Item("bamboo_sign", builder().stackSize(16)));
+    public static final Item CRIMSON_SIGN = register(new Item("crimson_sign", builder().stackSize(16)));
+    public static final Item WARPED_SIGN = register(new Item("warped_sign", builder().stackSize(16)));
+    public static final Item OAK_HANGING_SIGN = register(new Item("oak_hanging_sign", builder().stackSize(16)));
+    public static final Item SPRUCE_HANGING_SIGN = register(new Item("spruce_hanging_sign", builder().stackSize(16)));
+    public static final Item BIRCH_HANGING_SIGN = register(new Item("birch_hanging_sign", builder().stackSize(16)));
+    public static final Item JUNGLE_HANGING_SIGN = register(new Item("jungle_hanging_sign", builder().stackSize(16)));
+    public static final Item ACACIA_HANGING_SIGN = register(new Item("acacia_hanging_sign", builder().stackSize(16)));
+    public static final Item DARK_OAK_HANGING_SIGN = register(new Item("dark_oak_hanging_sign", builder().stackSize(16)));
+    public static final Item MANGROVE_HANGING_SIGN = register(new Item("mangrove_hanging_sign", builder().stackSize(16)));
+    public static final Item BAMBOO_HANGING_SIGN = register(new Item("bamboo_hanging_sign", builder().stackSize(16)));
+    public static final Item CRIMSON_HANGING_SIGN = register(new Item("crimson_hanging_sign", builder().stackSize(16)));
+    public static final Item WARPED_HANGING_SIGN = register(new Item("warped_hanging_sign", builder().stackSize(16)));
+    public static final Item BUCKET = register(new Item("bucket", builder().stackSize(16)));
+    public static final Item WATER_BUCKET = register(new Item("water_bucket", builder().stackSize(1)));
+    public static final Item LAVA_BUCKET = register(new Item("lava_bucket", builder().stackSize(1)));
+    public static final Item POWDER_SNOW_BUCKET = register(new Item("powder_snow_bucket", builder().stackSize(1)));
+    public static final Item SNOWBALL = register(new Item("snowball", builder().stackSize(16)));
+    public static final Item LEATHER = register(new Item("leather", builder()));
+    public static final Item MILK_BUCKET = register(new Item("milk_bucket", builder().stackSize(1)));
+    public static final Item PUFFERFISH_BUCKET = register(new Item("pufferfish_bucket", builder().stackSize(1)));
+    public static final Item SALMON_BUCKET = register(new Item("salmon_bucket", builder().stackSize(1)));
+    public static final Item COD_BUCKET = register(new Item("cod_bucket", builder().stackSize(1)));
+    public static final Item TROPICAL_FISH_BUCKET = register(new Item("tropical_fish_bucket", builder().stackSize(1)));
+    public static final Item AXOLOTL_BUCKET = register(new Item("axolotl_bucket", builder().stackSize(1)));
+    public static final Item TADPOLE_BUCKET = register(new Item("tadpole_bucket", builder().stackSize(1)));
+    public static final Item BRICK = register(new Item("brick", builder()));
+    public static final Item CLAY_BALL = register(new Item("clay_ball", builder()));
+    public static final Item DRIED_KELP_BLOCK = register(new Item("dried_kelp_block", builder()));
+    public static final Item PAPER = register(new Item("paper", builder()));
+    public static final Item BOOK = register(new Item("book", builder()));
+    public static final Item SLIME_BALL = register(new Item("slime_ball", builder()));
+    public static final Item EGG = register(new Item("egg", builder().stackSize(16)));
+    public static final CompassItem COMPASS = register(new CompassItem("compass", builder()));
+    public static final Item RECOVERY_COMPASS = register(new Item("recovery_compass", builder()));
+    public static final Item BUNDLE = register(new Item("bundle", builder().stackSize(1)));
+    public static final Item FISHING_ROD = register(new Item("fishing_rod", builder().stackSize(1).maxDamage(64)));
+    public static final Item CLOCK = register(new Item("clock", builder()));
+    public static final Item SPYGLASS = register(new Item("spyglass", builder().stackSize(1)));
+    public static final Item GLOWSTONE_DUST = register(new Item("glowstone_dust", builder()));
+    public static final Item COD = register(new Item("cod", builder()));
+    public static final Item SALMON = register(new Item("salmon", builder()));
+    public static final Item TROPICAL_FISH = register(new Item("tropical_fish", builder()));
+    public static final Item PUFFERFISH = register(new Item("pufferfish", builder()));
+    public static final Item COOKED_COD = register(new Item("cooked_cod", builder()));
+    public static final Item COOKED_SALMON = register(new Item("cooked_salmon", builder()));
+    public static final Item INK_SAC = register(new Item("ink_sac", builder()));
+    public static final Item GLOW_INK_SAC = register(new Item("glow_ink_sac", builder()));
+    public static final Item COCOA_BEANS = register(new Item("cocoa_beans", builder()));
+    public static final DyeItem WHITE_DYE = register(new DyeItem("white_dye", 0, builder()));
+    public static final DyeItem ORANGE_DYE = register(new DyeItem("orange_dye", 1, builder()));
+    public static final DyeItem MAGENTA_DYE = register(new DyeItem("magenta_dye", 2, builder()));
+    public static final DyeItem LIGHT_BLUE_DYE = register(new DyeItem("light_blue_dye", 3, builder()));
+    public static final DyeItem YELLOW_DYE = register(new DyeItem("yellow_dye", 4, builder()));
+    public static final DyeItem LIME_DYE = register(new DyeItem("lime_dye", 5, builder()));
+    public static final DyeItem PINK_DYE = register(new DyeItem("pink_dye", 6, builder()));
+    public static final DyeItem GRAY_DYE = register(new DyeItem("gray_dye", 7, builder()));
+    public static final DyeItem LIGHT_GRAY_DYE = register(new DyeItem("light_gray_dye", 8, builder()));
+    public static final DyeItem CYAN_DYE = register(new DyeItem("cyan_dye", 9, builder()));
+    public static final DyeItem PURPLE_DYE = register(new DyeItem("purple_dye", 10, builder()));
+    public static final DyeItem BLUE_DYE = register(new DyeItem("blue_dye", 11, builder()));
+    public static final DyeItem BROWN_DYE = register(new DyeItem("brown_dye", 12, builder()));
+    public static final DyeItem GREEN_DYE = register(new DyeItem("green_dye", 13, builder()));
+    public static final DyeItem RED_DYE = register(new DyeItem("red_dye", 14, builder()));
+    public static final DyeItem BLACK_DYE = register(new DyeItem("black_dye", 15, builder()));
+    public static final Item BONE_MEAL = register(new Item("bone_meal", builder()));
+    public static final Item BONE = register(new Item("bone", builder()));
+    public static final Item SUGAR = register(new Item("sugar", builder()));
+    public static final Item CAKE = register(new Item("cake", builder().stackSize(1)));
+    public static final Item WHITE_BED = register(new Item("white_bed", builder().stackSize(1)));
+    public static final Item ORANGE_BED = register(new Item("orange_bed", builder().stackSize(1)));
+    public static final Item MAGENTA_BED = register(new Item("magenta_bed", builder().stackSize(1)));
+    public static final Item LIGHT_BLUE_BED = register(new Item("light_blue_bed", builder().stackSize(1)));
+    public static final Item YELLOW_BED = register(new Item("yellow_bed", builder().stackSize(1)));
+    public static final Item LIME_BED = register(new Item("lime_bed", builder().stackSize(1)));
+    public static final Item PINK_BED = register(new Item("pink_bed", builder().stackSize(1)));
+    public static final Item GRAY_BED = register(new Item("gray_bed", builder().stackSize(1)));
+    public static final Item LIGHT_GRAY_BED = register(new Item("light_gray_bed", builder().stackSize(1)));
+    public static final Item CYAN_BED = register(new Item("cyan_bed", builder().stackSize(1)));
+    public static final Item PURPLE_BED = register(new Item("purple_bed", builder().stackSize(1)));
+    public static final Item BLUE_BED = register(new Item("blue_bed", builder().stackSize(1)));
+    public static final Item BROWN_BED = register(new Item("brown_bed", builder().stackSize(1)));
+    public static final Item GREEN_BED = register(new Item("green_bed", builder().stackSize(1)));
+    public static final Item RED_BED = register(new Item("red_bed", builder().stackSize(1)));
+    public static final Item BLACK_BED = register(new Item("black_bed", builder().stackSize(1)));
+    public static final Item COOKIE = register(new Item("cookie", builder()));
+    public static final FilledMapItem FILLED_MAP = register(new FilledMapItem("filled_map", builder()));
+    public static final Item SHEARS = register(new Item("shears", builder().stackSize(1).maxDamage(238)));
+    public static final Item MELON_SLICE = register(new Item("melon_slice", builder()));
+    public static final Item DRIED_KELP = register(new Item("dried_kelp", builder()));
+    public static final Item PUMPKIN_SEEDS = register(new Item("pumpkin_seeds", builder()));
+    public static final Item MELON_SEEDS = register(new Item("melon_seeds", builder()));
+    public static final Item BEEF = register(new Item("beef", builder()));
+    public static final Item COOKED_BEEF = register(new Item("cooked_beef", builder()));
+    public static final Item CHICKEN = register(new Item("chicken", builder()));
+    public static final Item COOKED_CHICKEN = register(new Item("cooked_chicken", builder()));
+    public static final Item ROTTEN_FLESH = register(new Item("rotten_flesh", builder()));
+    public static final Item ENDER_PEARL = register(new Item("ender_pearl", builder().stackSize(16)));
+    public static final Item BLAZE_ROD = register(new Item("blaze_rod", builder()));
+    public static final Item GHAST_TEAR = register(new Item("ghast_tear", builder()));
+    public static final Item GOLD_NUGGET = register(new Item("gold_nugget", builder()));
+    public static final Item NETHER_WART = register(new Item("nether_wart", builder()));
+    public static final PotionItem POTION = register(new PotionItem("potion", builder().stackSize(1)));
+    public static final Item GLASS_BOTTLE = register(new Item("glass_bottle", builder()));
+    public static final Item SPIDER_EYE = register(new Item("spider_eye", builder()));
+    public static final Item FERMENTED_SPIDER_EYE = register(new Item("fermented_spider_eye", builder()));
+    public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder()));
+    public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder()));
+    public static final Item BREWING_STAND = register(new Item("brewing_stand", builder()));
+    public static final Item CAULDRON = register(new Item("cauldron", builder()));
+    public static final Item ENDER_EYE = register(new Item("ender_eye", builder()));
+    public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder()));
+    public static final SpawnEggItem ALLAY_SPAWN_EGG = register(new SpawnEggItem("allay_spawn_egg", builder()));
+    public static final SpawnEggItem AXOLOTL_SPAWN_EGG = register(new SpawnEggItem("axolotl_spawn_egg", builder()));
+    public static final SpawnEggItem BAT_SPAWN_EGG = register(new SpawnEggItem("bat_spawn_egg", builder()));
+    public static final SpawnEggItem BEE_SPAWN_EGG = register(new SpawnEggItem("bee_spawn_egg", builder()));
+    public static final SpawnEggItem BLAZE_SPAWN_EGG = register(new SpawnEggItem("blaze_spawn_egg", builder()));
+    public static final SpawnEggItem CAT_SPAWN_EGG = register(new SpawnEggItem("cat_spawn_egg", builder()));
+    public static final SpawnEggItem CAMEL_SPAWN_EGG = register(new SpawnEggItem("camel_spawn_egg", builder()));
+    public static final SpawnEggItem CAVE_SPIDER_SPAWN_EGG = register(new SpawnEggItem("cave_spider_spawn_egg", builder()));
+    public static final SpawnEggItem CHICKEN_SPAWN_EGG = register(new SpawnEggItem("chicken_spawn_egg", builder()));
+    public static final SpawnEggItem COD_SPAWN_EGG = register(new SpawnEggItem("cod_spawn_egg", builder()));
+    public static final SpawnEggItem COW_SPAWN_EGG = register(new SpawnEggItem("cow_spawn_egg", builder()));
+    public static final SpawnEggItem CREEPER_SPAWN_EGG = register(new SpawnEggItem("creeper_spawn_egg", builder()));
+    public static final SpawnEggItem DOLPHIN_SPAWN_EGG = register(new SpawnEggItem("dolphin_spawn_egg", builder()));
+    public static final SpawnEggItem DONKEY_SPAWN_EGG = register(new SpawnEggItem("donkey_spawn_egg", builder()));
+    public static final SpawnEggItem DROWNED_SPAWN_EGG = register(new SpawnEggItem("drowned_spawn_egg", builder()));
+    public static final SpawnEggItem ELDER_GUARDIAN_SPAWN_EGG = register(new SpawnEggItem("elder_guardian_spawn_egg", builder()));
+    public static final SpawnEggItem ENDER_DRAGON_SPAWN_EGG = register(new SpawnEggItem("ender_dragon_spawn_egg", builder()));
+    public static final SpawnEggItem ENDERMAN_SPAWN_EGG = register(new SpawnEggItem("enderman_spawn_egg", builder()));
+    public static final SpawnEggItem ENDERMITE_SPAWN_EGG = register(new SpawnEggItem("endermite_spawn_egg", builder()));
+    public static final SpawnEggItem EVOKER_SPAWN_EGG = register(new SpawnEggItem("evoker_spawn_egg", builder()));
+    public static final SpawnEggItem FOX_SPAWN_EGG = register(new SpawnEggItem("fox_spawn_egg", builder()));
+    public static final SpawnEggItem FROG_SPAWN_EGG = register(new SpawnEggItem("frog_spawn_egg", builder()));
+    public static final SpawnEggItem GHAST_SPAWN_EGG = register(new SpawnEggItem("ghast_spawn_egg", builder()));
+    public static final SpawnEggItem GLOW_SQUID_SPAWN_EGG = register(new SpawnEggItem("glow_squid_spawn_egg", builder()));
+    public static final SpawnEggItem GOAT_SPAWN_EGG = register(new SpawnEggItem("goat_spawn_egg", builder()));
+    public static final SpawnEggItem GUARDIAN_SPAWN_EGG = register(new SpawnEggItem("guardian_spawn_egg", builder()));
+    public static final SpawnEggItem HOGLIN_SPAWN_EGG = register(new SpawnEggItem("hoglin_spawn_egg", builder()));
+    public static final SpawnEggItem HORSE_SPAWN_EGG = register(new SpawnEggItem("horse_spawn_egg", builder()));
+    public static final SpawnEggItem HUSK_SPAWN_EGG = register(new SpawnEggItem("husk_spawn_egg", builder()));
+    public static final SpawnEggItem IRON_GOLEM_SPAWN_EGG = register(new SpawnEggItem("iron_golem_spawn_egg", builder()));
+    public static final SpawnEggItem LLAMA_SPAWN_EGG = register(new SpawnEggItem("llama_spawn_egg", builder()));
+    public static final SpawnEggItem MAGMA_CUBE_SPAWN_EGG = register(new SpawnEggItem("magma_cube_spawn_egg", builder()));
+    public static final SpawnEggItem MOOSHROOM_SPAWN_EGG = register(new SpawnEggItem("mooshroom_spawn_egg", builder()));
+    public static final SpawnEggItem MULE_SPAWN_EGG = register(new SpawnEggItem("mule_spawn_egg", builder()));
+    public static final SpawnEggItem OCELOT_SPAWN_EGG = register(new SpawnEggItem("ocelot_spawn_egg", builder()));
+    public static final SpawnEggItem PANDA_SPAWN_EGG = register(new SpawnEggItem("panda_spawn_egg", builder()));
+    public static final SpawnEggItem PARROT_SPAWN_EGG = register(new SpawnEggItem("parrot_spawn_egg", builder()));
+    public static final SpawnEggItem PHANTOM_SPAWN_EGG = register(new SpawnEggItem("phantom_spawn_egg", builder()));
+    public static final SpawnEggItem PIG_SPAWN_EGG = register(new SpawnEggItem("pig_spawn_egg", builder()));
+    public static final SpawnEggItem PIGLIN_SPAWN_EGG = register(new SpawnEggItem("piglin_spawn_egg", builder()));
+    public static final SpawnEggItem PIGLIN_BRUTE_SPAWN_EGG = register(new SpawnEggItem("piglin_brute_spawn_egg", builder()));
+    public static final SpawnEggItem PILLAGER_SPAWN_EGG = register(new SpawnEggItem("pillager_spawn_egg", builder()));
+    public static final SpawnEggItem POLAR_BEAR_SPAWN_EGG = register(new SpawnEggItem("polar_bear_spawn_egg", builder()));
+    public static final SpawnEggItem PUFFERFISH_SPAWN_EGG = register(new SpawnEggItem("pufferfish_spawn_egg", builder()));
+    public static final SpawnEggItem RABBIT_SPAWN_EGG = register(new SpawnEggItem("rabbit_spawn_egg", builder()));
+    public static final SpawnEggItem RAVAGER_SPAWN_EGG = register(new SpawnEggItem("ravager_spawn_egg", builder()));
+    public static final SpawnEggItem SALMON_SPAWN_EGG = register(new SpawnEggItem("salmon_spawn_egg", builder()));
+    public static final SpawnEggItem SHEEP_SPAWN_EGG = register(new SpawnEggItem("sheep_spawn_egg", builder()));
+    public static final SpawnEggItem SHULKER_SPAWN_EGG = register(new SpawnEggItem("shulker_spawn_egg", builder()));
+    public static final SpawnEggItem SILVERFISH_SPAWN_EGG = register(new SpawnEggItem("silverfish_spawn_egg", builder()));
+    public static final SpawnEggItem SKELETON_SPAWN_EGG = register(new SpawnEggItem("skeleton_spawn_egg", builder()));
+    public static final SpawnEggItem SKELETON_HORSE_SPAWN_EGG = register(new SpawnEggItem("skeleton_horse_spawn_egg", builder()));
+    public static final SpawnEggItem SLIME_SPAWN_EGG = register(new SpawnEggItem("slime_spawn_egg", builder()));
+    public static final SpawnEggItem SNOW_GOLEM_SPAWN_EGG = register(new SpawnEggItem("snow_golem_spawn_egg", builder()));
+    public static final SpawnEggItem SPIDER_SPAWN_EGG = register(new SpawnEggItem("spider_spawn_egg", builder()));
+    public static final SpawnEggItem SQUID_SPAWN_EGG = register(new SpawnEggItem("squid_spawn_egg", builder()));
+    public static final SpawnEggItem STRAY_SPAWN_EGG = register(new SpawnEggItem("stray_spawn_egg", builder()));
+    public static final SpawnEggItem STRIDER_SPAWN_EGG = register(new SpawnEggItem("strider_spawn_egg", builder()));
+    public static final SpawnEggItem TADPOLE_SPAWN_EGG = register(new SpawnEggItem("tadpole_spawn_egg", builder()));
+    public static final SpawnEggItem TRADER_LLAMA_SPAWN_EGG = register(new SpawnEggItem("trader_llama_spawn_egg", builder()));
+    public static final SpawnEggItem TROPICAL_FISH_SPAWN_EGG = register(new SpawnEggItem("tropical_fish_spawn_egg", builder()));
+    public static final SpawnEggItem TURTLE_SPAWN_EGG = register(new SpawnEggItem("turtle_spawn_egg", builder()));
+    public static final SpawnEggItem VEX_SPAWN_EGG = register(new SpawnEggItem("vex_spawn_egg", builder()));
+    public static final SpawnEggItem VILLAGER_SPAWN_EGG = register(new SpawnEggItem("villager_spawn_egg", builder()));
+    public static final SpawnEggItem VINDICATOR_SPAWN_EGG = register(new SpawnEggItem("vindicator_spawn_egg", builder()));
+    public static final SpawnEggItem WANDERING_TRADER_SPAWN_EGG = register(new SpawnEggItem("wandering_trader_spawn_egg", builder()));
+    public static final SpawnEggItem WARDEN_SPAWN_EGG = register(new SpawnEggItem("warden_spawn_egg", builder()));
+    public static final SpawnEggItem WITCH_SPAWN_EGG = register(new SpawnEggItem("witch_spawn_egg", builder()));
+    public static final SpawnEggItem WITHER_SPAWN_EGG = register(new SpawnEggItem("wither_spawn_egg", builder()));
+    public static final SpawnEggItem WITHER_SKELETON_SPAWN_EGG = register(new SpawnEggItem("wither_skeleton_spawn_egg", builder()));
+    public static final SpawnEggItem WOLF_SPAWN_EGG = register(new SpawnEggItem("wolf_spawn_egg", builder()));
+    public static final SpawnEggItem ZOGLIN_SPAWN_EGG = register(new SpawnEggItem("zoglin_spawn_egg", builder()));
+    public static final SpawnEggItem ZOMBIE_SPAWN_EGG = register(new SpawnEggItem("zombie_spawn_egg", builder()));
+    public static final SpawnEggItem ZOMBIE_HORSE_SPAWN_EGG = register(new SpawnEggItem("zombie_horse_spawn_egg", builder()));
+    public static final SpawnEggItem ZOMBIE_VILLAGER_SPAWN_EGG = register(new SpawnEggItem("zombie_villager_spawn_egg", builder()));
+    public static final SpawnEggItem ZOMBIFIED_PIGLIN_SPAWN_EGG = register(new SpawnEggItem("zombified_piglin_spawn_egg", builder()));
+    public static final Item EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder()));
+    public static final Item FIRE_CHARGE = register(new Item("fire_charge", builder()));
+    public static final Item WRITABLE_BOOK = register(new Item("writable_book", builder().stackSize(1)));
+    public static final Item WRITTEN_BOOK = register(new Item("written_book", builder().stackSize(16)));
+    public static final Item ITEM_FRAME = register(new Item("item_frame", builder()));
+    public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder()));
+    public static final Item FLOWER_POT = register(new Item("flower_pot", builder()));
+    public static final Item CARROT = register(new Item("carrot", builder()));
+    public static final Item POTATO = register(new Item("potato", builder()));
+    public static final Item BAKED_POTATO = register(new Item("baked_potato", builder()));
+    public static final Item POISONOUS_POTATO = register(new Item("poisonous_potato", builder()));
+    public static final MapItem MAP = register(new MapItem("map", builder()));
+    public static final Item GOLDEN_CARROT = register(new Item("golden_carrot", builder()));
+    public static final Item SKELETON_SKULL = register(new Item("skeleton_skull", builder()));
+    public static final Item WITHER_SKELETON_SKULL = register(new Item("wither_skeleton_skull", builder()));
+    public static final Item PLAYER_HEAD = register(new Item("player_head", builder()));
+    public static final Item ZOMBIE_HEAD = register(new Item("zombie_head", builder()));
+    public static final Item CREEPER_HEAD = register(new Item("creeper_head", builder()));
+    public static final Item DRAGON_HEAD = register(new Item("dragon_head", builder()));
+    public static final Item PIGLIN_HEAD = register(new Item("piglin_head", builder()));
+    public static final Item NETHER_STAR = register(new Item("nether_star", builder()));
+    public static final Item PUMPKIN_PIE = register(new Item("pumpkin_pie", builder()));
+    public static final Item FIREWORK_ROCKET = register(new Item("firework_rocket", builder()));
+    public static final Item FIREWORK_STAR = register(new Item("firework_star", builder()));
+    public static final Item ENCHANTED_BOOK = register(new Item("enchanted_book", builder().stackSize(1)));
+    public static final Item NETHER_BRICK = register(new Item("nether_brick", builder()));
+    public static final Item PRISMARINE_SHARD = register(new Item("prismarine_shard", builder()));
+    public static final Item PRISMARINE_CRYSTALS = register(new Item("prismarine_crystals", builder()));
+    public static final Item RABBIT = register(new Item("rabbit", builder()));
+    public static final Item COOKED_RABBIT = register(new Item("cooked_rabbit", builder()));
+    public static final Item RABBIT_STEW = register(new Item("rabbit_stew", builder().stackSize(1)));
+    public static final Item RABBIT_FOOT = register(new Item("rabbit_foot", builder()));
+    public static final Item RABBIT_HIDE = register(new Item("rabbit_hide", builder()));
+    public static final Item ARMOR_STAND = register(new Item("armor_stand", builder().stackSize(16)));
+    public static final Item IRON_HORSE_ARMOR = register(new Item("iron_horse_armor", builder().stackSize(1)));
+    public static final Item GOLDEN_HORSE_ARMOR = register(new Item("golden_horse_armor", builder().stackSize(1)));
+    public static final Item DIAMOND_HORSE_ARMOR = register(new Item("diamond_horse_armor", builder().stackSize(1)));
+    public static final Item LEATHER_HORSE_ARMOR = register(new Item("leather_horse_armor", builder().stackSize(1)));
+    public static final Item LEAD = register(new Item("lead", builder()));
+    public static final Item NAME_TAG = register(new Item("name_tag", builder()));
+    public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1)));
+    public static final Item MUTTON = register(new Item("mutton", builder()));
+    public static final Item COOKED_MUTTON = register(new Item("cooked_mutton", builder()));
+    public static final Item WHITE_BANNER = register(new Item("white_banner", builder().stackSize(16)));
+    public static final Item ORANGE_BANNER = register(new Item("orange_banner", builder().stackSize(16)));
+    public static final Item MAGENTA_BANNER = register(new Item("magenta_banner", builder().stackSize(16)));
+    public static final Item LIGHT_BLUE_BANNER = register(new Item("light_blue_banner", builder().stackSize(16)));
+    public static final Item YELLOW_BANNER = register(new Item("yellow_banner", builder().stackSize(16)));
+    public static final Item LIME_BANNER = register(new Item("lime_banner", builder().stackSize(16)));
+    public static final Item PINK_BANNER = register(new Item("pink_banner", builder().stackSize(16)));
+    public static final Item GRAY_BANNER = register(new Item("gray_banner", builder().stackSize(16)));
+    public static final Item LIGHT_GRAY_BANNER = register(new Item("light_gray_banner", builder().stackSize(16)));
+    public static final Item CYAN_BANNER = register(new Item("cyan_banner", builder().stackSize(16)));
+    public static final Item PURPLE_BANNER = register(new Item("purple_banner", builder().stackSize(16)));
+    public static final Item BLUE_BANNER = register(new Item("blue_banner", builder().stackSize(16)));
+    public static final Item BROWN_BANNER = register(new Item("brown_banner", builder().stackSize(16)));
+    public static final Item GREEN_BANNER = register(new Item("green_banner", builder().stackSize(16)));
+    public static final Item RED_BANNER = register(new Item("red_banner", builder().stackSize(16)));
+    public static final Item BLACK_BANNER = register(new Item("black_banner", builder().stackSize(16)));
+    public static final Item END_CRYSTAL = register(new Item("end_crystal", builder()));
+    public static final Item CHORUS_FRUIT = register(new Item("chorus_fruit", builder()));
+    public static final Item POPPED_CHORUS_FRUIT = register(new Item("popped_chorus_fruit", builder()));
+    public static final Item BEETROOT = register(new Item("beetroot", builder()));
+    public static final Item BEETROOT_SEEDS = register(new Item("beetroot_seeds", builder()));
+    public static final Item BEETROOT_SOUP = register(new Item("beetroot_soup", builder().stackSize(1)));
+    public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder()));
+    public static final PotionItem SPLASH_POTION = register(new PotionItem("splash_potion", builder().stackSize(1)));
+    public static final Item SPECTRAL_ARROW = register(new Item("spectral_arrow", builder()));
+    public static final TippedArrowItem TIPPED_ARROW = register(new TippedArrowItem("tipped_arrow", builder()));
+    public static final PotionItem LINGERING_POTION = register(new PotionItem("lingering_potion", builder().stackSize(1)));
+    public static final Item SHIELD = register(new Item("shield", builder().stackSize(1).maxDamage(336)));
+    public static final Item TOTEM_OF_UNDYING = register(new Item("totem_of_undying", builder().stackSize(1)));
+    public static final Item SHULKER_SHELL = register(new Item("shulker_shell", builder()));
+    public static final Item IRON_NUGGET = register(new Item("iron_nugget", builder()));
+    public static final Item KNOWLEDGE_BOOK = register(new Item("knowledge_book", builder().stackSize(1)));
+    public static final Item DEBUG_STICK = register(new Item("debug_stick", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_13 = register(new Item("music_disc_13", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_CAT = register(new Item("music_disc_cat", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_BLOCKS = register(new Item("music_disc_blocks", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_CHIRP = register(new Item("music_disc_chirp", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_FAR = register(new Item("music_disc_far", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_MALL = register(new Item("music_disc_mall", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_MELLOHI = register(new Item("music_disc_mellohi", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_STAL = register(new Item("music_disc_stal", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_STRAD = register(new Item("music_disc_strad", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_WARD = register(new Item("music_disc_ward", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_11 = register(new Item("music_disc_11", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_WAIT = register(new Item("music_disc_wait", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_OTHERSIDE = register(new Item("music_disc_otherside", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder().stackSize(1)));
+    public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1)));
+    public static final Item DISC_FRAGMENT_5 = register(new Item("disc_fragment_5", builder()));
+    public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250)));
+    public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder()));
+    public static final Item NAUTILUS_SHELL = register(new Item("nautilus_shell", builder()));
+    public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder()));
+    public static final Item CROSSBOW = register(new Item("crossbow", builder().stackSize(1).maxDamage(465)));
+    public static final Item SUSPICIOUS_STEW = register(new Item("suspicious_stew", builder().stackSize(1)));
+    public static final Item LOOM = register(new Item("loom", builder()));
+    public static final Item FLOWER_BANNER_PATTERN = register(new Item("flower_banner_pattern", builder().stackSize(1)));
+    public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder().stackSize(1)));
+    public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1)));
+    public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder().stackSize(1)));
+    public static final Item GLOBE_BANNER_PATTERN = register(new Item("globe_banner_pattern", builder().stackSize(1)));
+    public static final Item PIGLIN_BANNER_PATTERN = register(new Item("piglin_banner_pattern", builder().stackSize(1)));
+    public static final GoatHornItem GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1)));
+    public static final Item COMPOSTER = register(new Item("composter", builder()));
+    public static final Item BARREL = register(new Item("barrel", builder()));
+    public static final Item SMOKER = register(new Item("smoker", builder()));
+    public static final Item BLAST_FURNACE = register(new Item("blast_furnace", builder()));
+    public static final Item CARTOGRAPHY_TABLE = register(new Item("cartography_table", builder()));
+    public static final Item FLETCHING_TABLE = register(new Item("fletching_table", builder()));
+    public static final Item GRINDSTONE = register(new Item("grindstone", builder()));
+    public static final Item SMITHING_TABLE = register(new Item("smithing_table", builder()));
+    public static final Item STONECUTTER = register(new Item("stonecutter", builder()));
+    public static final Item BELL = register(new Item("bell", builder()));
+    public static final Item LANTERN = register(new Item("lantern", builder()));
+    public static final Item SOUL_LANTERN = register(new Item("soul_lantern", builder()));
+    public static final Item SWEET_BERRIES = register(new Item("sweet_berries", builder()));
+    public static final Item GLOW_BERRIES = register(new Item("glow_berries", builder()));
+    public static final Item CAMPFIRE = register(new Item("campfire", builder()));
+    public static final Item SOUL_CAMPFIRE = register(new Item("soul_campfire", builder()));
+    public static final Item SHROOMLIGHT = register(new Item("shroomlight", builder()));
+    public static final Item HONEYCOMB = register(new Item("honeycomb", builder()));
+    public static final Item BEE_NEST = register(new Item("bee_nest", builder()));
+    public static final Item BEEHIVE = register(new Item("beehive", builder()));
+    public static final Item HONEY_BOTTLE = register(new Item("honey_bottle", builder().stackSize(16)));
+    public static final Item HONEYCOMB_BLOCK = register(new Item("honeycomb_block", builder()));
+    public static final Item LODESTONE = register(new Item("lodestone", builder()));
+    public static final Item CRYING_OBSIDIAN = register(new Item("crying_obsidian", builder()));
+    public static final Item BLACKSTONE = register(new Item("blackstone", builder()));
+    public static final Item BLACKSTONE_SLAB = register(new Item("blackstone_slab", builder()));
+    public static final Item BLACKSTONE_STAIRS = register(new Item("blackstone_stairs", builder()));
+    public static final Item GILDED_BLACKSTONE = register(new Item("gilded_blackstone", builder()));
+    public static final Item POLISHED_BLACKSTONE = register(new Item("polished_blackstone", builder()));
+    public static final Item POLISHED_BLACKSTONE_SLAB = register(new Item("polished_blackstone_slab", builder()));
+    public static final Item POLISHED_BLACKSTONE_STAIRS = register(new Item("polished_blackstone_stairs", builder()));
+    public static final Item CHISELED_POLISHED_BLACKSTONE = register(new Item("chiseled_polished_blackstone", builder()));
+    public static final Item POLISHED_BLACKSTONE_BRICKS = register(new Item("polished_blackstone_bricks", builder()));
+    public static final Item POLISHED_BLACKSTONE_BRICK_SLAB = register(new Item("polished_blackstone_brick_slab", builder()));
+    public static final Item POLISHED_BLACKSTONE_BRICK_STAIRS = register(new Item("polished_blackstone_brick_stairs", builder()));
+    public static final Item CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new Item("cracked_polished_blackstone_bricks", builder()));
+    public static final Item RESPAWN_ANCHOR = register(new Item("respawn_anchor", builder()));
+    public static final Item CANDLE = register(new Item("candle", builder()));
+    public static final Item WHITE_CANDLE = register(new Item("white_candle", builder()));
+    public static final Item ORANGE_CANDLE = register(new Item("orange_candle", builder()));
+    public static final Item MAGENTA_CANDLE = register(new Item("magenta_candle", builder()));
+    public static final Item LIGHT_BLUE_CANDLE = register(new Item("light_blue_candle", builder()));
+    public static final Item YELLOW_CANDLE = register(new Item("yellow_candle", builder()));
+    public static final Item LIME_CANDLE = register(new Item("lime_candle", builder()));
+    public static final Item PINK_CANDLE = register(new Item("pink_candle", builder()));
+    public static final Item GRAY_CANDLE = register(new Item("gray_candle", builder()));
+    public static final Item LIGHT_GRAY_CANDLE = register(new Item("light_gray_candle", builder()));
+    public static final Item CYAN_CANDLE = register(new Item("cyan_candle", builder()));
+    public static final Item PURPLE_CANDLE = register(new Item("purple_candle", builder()));
+    public static final Item BLUE_CANDLE = register(new Item("blue_candle", builder()));
+    public static final Item BROWN_CANDLE = register(new Item("brown_candle", builder()));
+    public static final Item GREEN_CANDLE = register(new Item("green_candle", builder()));
+    public static final Item RED_CANDLE = register(new Item("red_candle", builder()));
+    public static final Item BLACK_CANDLE = register(new Item("black_candle", builder()));
+    public static final Item SMALL_AMETHYST_BUD = register(new Item("small_amethyst_bud", builder()));
+    public static final Item MEDIUM_AMETHYST_BUD = register(new Item("medium_amethyst_bud", builder()));
+    public static final Item LARGE_AMETHYST_BUD = register(new Item("large_amethyst_bud", builder()));
+    public static final Item AMETHYST_CLUSTER = register(new Item("amethyst_cluster", builder()));
+    public static final Item POINTED_DRIPSTONE = register(new Item("pointed_dripstone", builder()));
+    public static final Item OCHRE_FROGLIGHT = register(new Item("ochre_froglight", builder()));
+    public static final Item VERDANT_FROGLIGHT = register(new Item("verdant_froglight", builder()));
+    public static final Item PEARLESCENT_FROGLIGHT = register(new Item("pearlescent_froglight", builder()));
+    public static final Item FROGSPAWN = register(new Item("frogspawn", builder()));
+    public static final Item ECHO_SHARD = register(new Item("echo_shard", builder()));
+
+    private static <T extends Item> T register(T item) {
+        return register(item, Registries.JAVA_ITEMS.get().size());
+    }
+
+    public static <T extends Item> T register(T item, int id) {
+        item.setJavaId(id);
+        Registries.JAVA_ITEMS.get().add(item);
+        Registries.JAVA_ITEM_IDENTIFIERS.register(item.javaIdentifier(), item);
+        return item;
+    }
+
+    private Items() {
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java
new file mode 100644
index 000000000..9a93eeac8
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.item.type;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
+import com.github.steveice10.opennbt.tag.builtin.StringTag;
+import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
+import org.geysermc.geyser.inventory.item.TippedArrowPotion;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.registry.type.ItemMappings;
+
+public class ArrowItem extends Item {
+    public ArrowItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
+
+    public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
+        TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage());
+        ItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
+        if (tippedArrowPotion != null) {
+            itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getNbt());
+            StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier());
+            itemStack.getNbt().put(potionTag);
+        }
+        return itemStack;
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java
new file mode 100644
index 000000000..0dbf0971a
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.item.type;
+
+/**
+ * TODO needed?
+ */
+public class BlockItem extends Item {
+    public BlockItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java
similarity index 75%
rename from core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java
rename to core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java
index a6750e7d7..e7922b9d3 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java
@@ -23,27 +23,23 @@
  * @link https://github.com/GeyserMC/Geyser
  */
 
-package org.geysermc.geyser.translator.inventory.item;
+package org.geysermc.geyser.item.type;
 
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
 import com.github.steveice10.opennbt.tag.builtin.ByteTag;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.Tag;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
-import org.geysermc.geyser.network.GameProtocol;
-import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.registry.type.ItemMappings;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@ItemRemapper
-public class CompassTranslator extends ItemTranslator {
+public class CompassItem extends Item {
+    public CompassItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
 
     @Override
-    protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
+    public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
         if (isLodestoneCompass(itemStack.getNbt())) {
             // NBT will be translated in nbt/LodestoneCompassTranslator if applicable
             return super.translateToBedrock(itemStack, mappings.getLodestoneCompass(), mappings);
@@ -52,11 +48,11 @@ public class CompassTranslator extends ItemTranslator {
     }
 
     @Override
-    protected ItemMapping getItemMapping(int javaId, CompoundTag nbt, ItemMappings mappings) {
+    public ItemMapping toBedrockDefinition(CompoundTag nbt, ItemMappings mappings) {
         if (isLodestoneCompass(nbt)) {
             return mappings.getLodestoneCompass();
         }
-        return super.getItemMapping(javaId, nbt, mappings);
+        return super.toBedrockDefinition(nbt, mappings);
     }
 
     private boolean isLodestoneCompass(CompoundTag nbt) {
@@ -76,11 +72,4 @@ public class CompassTranslator extends ItemTranslator {
 
         return super.translateToJava(itemData, mapping, mappings);
     }
-
-    @Override
-    public List<ItemMapping> getAppliedItems() {
-        return Arrays.stream(Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getItems())
-                .filter(entry -> entry.getJavaIdentifier().endsWith("compass"))
-                .collect(Collectors.toList());
-    }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeItem.java
new file mode 100644
index 000000000..329590379
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeItem.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.item.type;
+
+public class DyeItem extends Item {
+    private final int dyeColor;
+
+    public DyeItem(String javaIdentifier, int dyeColor, Builder builder) {
+        super(javaIdentifier, builder);
+        this.dyeColor = dyeColor;
+    }
+
+    public int dyeColor() {
+        return dyeColor;
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/FilledMapTranslator.java b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java
similarity index 77%
rename from core/src/main/java/org/geysermc/geyser/translator/inventory/item/FilledMapTranslator.java
rename to core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java
index c559fb247..d045f83e4 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/FilledMapTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java
@@ -23,25 +23,22 @@
  * @link https://github.com/GeyserMC/Geyser
  */
 
-package org.geysermc.geyser.translator.inventory.item;
+package org.geysermc.geyser.item.type;
 
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.Tag;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
-import org.geysermc.geyser.network.GameProtocol;
-import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.registry.type.ItemMappings;
 
-import java.util.Collections;
-import java.util.List;
-
-@ItemRemapper
-public class FilledMapTranslator extends ItemTranslator {
+public class FilledMapItem extends MapItem {
+    public FilledMapItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
 
     @Override
-    protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
+    public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
         ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings);
         CompoundTag nbt = itemStack.getNbt();
         if (nbt != null && nbt.get("display") instanceof CompoundTag display) {
@@ -57,12 +54,4 @@ public class FilledMapTranslator extends ItemTranslator {
         }
         return builder;
     }
-
-    @Override
-    public List<ItemMapping> getAppliedItems() {
-        return Collections.singletonList(
-                Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
-                        .getMapping("minecraft:filled_map")
-        );
-    }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java
similarity index 84%
rename from core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java
rename to core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java
index 8f0c9f5f2..4c21be833 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java
@@ -23,23 +23,18 @@
  * @link https://github.com/GeyserMC/Geyser
  */
 
-package org.geysermc.geyser.translator.inventory.item;
+package org.geysermc.geyser.item.type;
 
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
 import com.github.steveice10.opennbt.tag.builtin.StringTag;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.network.GameProtocol;
-import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.registry.type.ItemMappings;
 
-import java.util.Collections;
 import java.util.List;
 
-@ItemRemapper
-public class GoatHornTranslator extends ItemTranslator {
-
+public class GoatHornItem extends Item {
     private static final List<String> INSTRUMENTS = List.of(
             "ponder_goat_horn",
             "sing_goat_horn",
@@ -51,8 +46,12 @@ public class GoatHornTranslator extends ItemTranslator {
             "dream_goat_horn" // Called "Resist" on Bedrock 1.19.0 due to https://bugs.mojang.com/browse/MCPE-155059
     );
 
+    public GoatHornItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
+
     @Override
-    protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
+    public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
         ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings);
         if (itemStack.getNbt() != null && itemStack.getNbt().get("instrument") instanceof StringTag instrumentTag) {
             String instrument = instrumentTag.getValue();
@@ -87,12 +86,4 @@ public class GoatHornTranslator extends ItemTranslator {
 
         return itemStack;
     }
-
-    @Override
-    public List<ItemMapping> getAppliedItems() {
-        return Collections.singletonList(
-                Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
-                        .getMapping("minecraft:goat_horn")
-        );
-    }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java
new file mode 100644
index 000000000..af96d6094
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.item.type;
+
+import com.github.steveice10.mc.protocol.data.game.Identifier;
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
+import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
+import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.registry.type.ItemMappings;
+import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
+
+import javax.annotation.Nullable;
+import java.util.Set;
+
+public class Item {
+    private final String javaIdentifier;
+    private int javaId = -1;
+    private final int stackSize;
+    private final String toolType;
+    private final String toolTier;
+    private final int maxDamage;
+    private final Set<String> repairMaterials;
+    private final boolean hasSuspiciousStewEffect;
+
+    public Item(String javaIdentifier, Builder builder) {
+        this.javaIdentifier = Identifier.formalize(javaIdentifier).intern();
+        this.stackSize = builder.stackSize;
+        this.toolType = builder.toolType;
+        this.toolTier = builder.toolTier;
+        this.maxDamage = builder.maxDamage;
+        this.repairMaterials = builder.repairMaterials;
+        this.hasSuspiciousStewEffect = builder.hasSuspiciousStewEffect;
+    }
+
+    public String javaIdentifier() {
+        return javaIdentifier;
+    }
+
+    public int javaId() {
+        return javaId;
+    }
+
+    public int maxDamage() {
+        return maxDamage;
+    }
+
+    public int maxStackSize() {
+        return stackSize;
+    }
+
+    public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
+        if (itemStack == null) {
+            // Return, essentially, air
+            return ItemData.builder();
+        }
+        ItemData.Builder builder = ItemData.builder()
+                .definition(mapping.getBedrockDefinition())
+                .damage(mapping.getBedrockData())
+                .count(itemStack.getAmount());
+        if (itemStack.getNbt() != null) {
+            builder.tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt()));
+        }
+
+        CompoundTag nbt = itemStack.getNbt();
+        ItemTranslator.translateCustomItem(nbt, builder, mapping);
+
+        return builder;
+    }
+
+    public ItemStack translateToJava(@Nullable ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
+        if (itemData == null) return null;
+        if (itemData.getTag() == null) {
+            return new ItemStack(javaId, itemData.getCount(), new CompoundTag(""));
+        }
+        return new ItemStack(javaId, itemData.getCount(), ItemTranslator.translateToJavaNBT("", itemData.getTag()));
+    }
+
+    public ItemMapping toBedrockDefinition(CompoundTag nbt, ItemMappings mappings) {
+        return mappings.getMapping(javaId);
+    }
+
+    public ItemStack newItemStack(int count, CompoundTag tag) {
+        return new ItemStack(this.javaId, count, tag);
+    }
+
+    public void setJavaId(int javaId) { // TODO like this?
+        if (this.javaId != -1) { // ID has already been set.
+            throw new RuntimeException();
+        }
+        this.javaId = javaId;
+    }
+
+    @Override
+    public String toString() {
+        return "Item{" +
+                "javaIdentifier='" + javaIdentifier + '\'' +
+                ", javaId=" + javaId +
+                '}';
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static final class Builder {
+        private int stackSize = 64;
+        private String toolType;
+        private String toolTier;
+        private int maxDamage;
+        private Set<String> repairMaterials;
+        private boolean hasSuspiciousStewEffect;
+
+        public Builder stackSize(int stackSize) {
+            this.stackSize = stackSize;
+            return this;
+        }
+
+        public Builder setToolType(String toolType) {
+            this.toolType = toolType;
+            return this;
+        }
+
+        public Builder setToolTier(String toolTier) {
+            this.toolTier = toolTier;
+            return this;
+        }
+
+        public Builder maxDamage(int maxDamage) {
+            this.maxDamage = maxDamage;
+            return this;
+        }
+
+        public Builder setRepairMaterials(Set<String> repairMaterials) {
+            this.repairMaterials = repairMaterials;
+            return this;
+        }
+
+        public Builder setHasSuspiciousStewEffect(boolean hasSuspiciousStewEffect) {
+            this.hasSuspiciousStewEffect = hasSuspiciousStewEffect;
+            return this;
+        }
+
+        private Builder() {
+        }
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java
new file mode 100644
index 000000000..3add04498
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/type/MapItem.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.item.type;
+
+public class MapItem extends Item {
+    public MapItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java
similarity index 78%
rename from core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java
rename to core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java
index b82ccc128..b2251ff0f 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java
@@ -23,7 +23,7 @@
  * @link https://github.com/GeyserMC/Geyser
  */
 
-package org.geysermc.geyser.translator.inventory.item;
+package org.geysermc.geyser.item.type;
 
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
 import com.github.steveice10.opennbt.tag.builtin.StringTag;
@@ -31,20 +31,17 @@ import com.github.steveice10.opennbt.tag.builtin.Tag;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import org.geysermc.geyser.GeyserImpl;
 import org.geysermc.geyser.inventory.item.Potion;
-import org.geysermc.geyser.network.GameProtocol;
-import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.registry.type.ItemMappings;
+import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@ItemRemapper
-public class PotionTranslator extends ItemTranslator {
+public class PotionItem extends Item {
+    public PotionItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
 
     @Override
-    protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
+    public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
         if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, mapping, mappings);
         Tag potionTag = itemStack.getNbt().get("Potion");
         if (potionTag instanceof StringTag) {
@@ -54,7 +51,7 @@ public class PotionTranslator extends ItemTranslator {
                         .definition(mapping.getBedrockDefinition())
                         .damage(potion.getBedrockId())
                         .count(itemStack.getAmount())
-                        .tag(translateNbtToBedrock(itemStack.getNbt()));
+                        .tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt()));
             }
             GeyserImpl.getInstance().getLogger().debug("Unknown Java potion: " + potionTag.getValue());
         }
@@ -71,11 +68,4 @@ public class PotionTranslator extends ItemTranslator {
         }
         return itemStack;
     }
-
-    @Override
-    public List<ItemMapping> getAppliedItems() {
-        return Arrays.stream(Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getItems())
-                .filter(entry -> entry.getJavaIdentifier().endsWith("potion"))
-                .collect(Collectors.toList());
-    }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/SpawnEggItem.java b/core/src/main/java/org/geysermc/geyser/item/type/SpawnEggItem.java
new file mode 100644
index 000000000..272e00408
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/type/SpawnEggItem.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.item.type;
+
+public class SpawnEggItem extends Item {
+    public SpawnEggItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TieredItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TieredItem.java
new file mode 100644
index 000000000..14db36bf3
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/type/TieredItem.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.item.type;
+
+/**
+ * May not represent all tiered items - just the ones we care about. :)
+ */
+public class TieredItem extends Item {
+    public TieredItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java
similarity index 54%
rename from core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java
rename to core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java
index 7b141ab36..f78836d16 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java
@@ -23,7 +23,7 @@
  * @link https://github.com/GeyserMC/Geyser
  */
 
-package org.geysermc.geyser.translator.inventory.item;
+package org.geysermc.geyser.item.type;
 
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
 import com.github.steveice10.opennbt.tag.builtin.StringTag;
@@ -31,27 +31,17 @@ import com.github.steveice10.opennbt.tag.builtin.Tag;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import org.geysermc.geyser.GeyserImpl;
 import org.geysermc.geyser.inventory.item.TippedArrowPotion;
-import org.geysermc.geyser.network.GameProtocol;
-import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.registry.type.ItemMappings;
+import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@ItemRemapper
-public class TippedArrowTranslator extends ItemTranslator {
-    private static final int TIPPED_ARROW_JAVA_ID = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
-            .getMapping("minecraft:tipped_arrow")
-            .getJavaId();
+public class TippedArrowItem extends ArrowItem {
+    public TippedArrowItem(String javaIdentifier, Builder builder) {
+        super(javaIdentifier, builder);
+    }
 
     @Override
-    protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
-        if (!mapping.getJavaIdentifier().equals("minecraft:tipped_arrow") || itemStack.getNbt() == null) {
-            // We're only concerned about minecraft:arrow when translating Bedrock -> Java
-            return super.translateToBedrock(itemStack, mapping, mappings);
-        }
+    public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
         Tag potionTag = itemStack.getNbt().get("Potion");
         if (potionTag instanceof StringTag) {
             TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByJavaIdentifier(((StringTag) potionTag).getValue());
@@ -60,30 +50,10 @@ public class TippedArrowTranslator extends ItemTranslator {
                         .definition(mapping.getBedrockDefinition())
                         .damage(tippedArrowPotion.getBedrockId())
                         .count(itemStack.getAmount())
-                        .tag(translateNbtToBedrock(itemStack.getNbt()));
+                        .tag(ItemTranslator.translateNbtToBedrock(itemStack.getNbt()));
             }
             GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionTag.getValue());
         }
         return super.translateToBedrock(itemStack, mapping, mappings);
     }
-
-    @Override
-    public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
-        TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage());
-        ItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
-        if (tippedArrowPotion != null) {
-            itemStack = new ItemStack(TIPPED_ARROW_JAVA_ID, itemStack.getAmount(), itemStack.getNbt());
-            StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier());
-            itemStack.getNbt().put(potionTag);
-        }
-        return itemStack;
-    }
-
-    @Override
-    public List<ItemMapping> getAppliedItems() {
-        return Arrays.stream(Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getItems())
-                .filter(entry -> entry.getJavaIdentifier().contains("arrow")
-                        && !entry.getJavaIdentifier().contains("spectral"))
-                .collect(Collectors.toList());
-    }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java
index 669d058d4..19e66cf5e 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java
@@ -44,6 +44,7 @@ import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
 import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.loader.*;
 import org.geysermc.geyser.registry.populator.ItemRegistryPopulator;
 import org.geysermc.geyser.registry.populator.PacketRegistryPopulator;
@@ -120,6 +121,10 @@ public final class Registries {
      */
     public static final PacketTranslatorRegistry<Packet> JAVA_PACKET_TRANSLATORS = PacketTranslatorRegistry.create();
 
+    public static final SimpleRegistry<List<Item>> JAVA_ITEMS = SimpleRegistry.create(RegistryLoaders.empty(ArrayList::new));
+
+    public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
+
     /**
      * A versioned registry which holds {@link ItemMappings} for each version. These item mappings contain
      * primarily Bedrock version-specific data.
diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java
index 8ad09bf88..cbd992c54 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java
@@ -30,10 +30,9 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
 import it.unimi.dsi.fastutil.ints.IntSet;
 import org.geysermc.geyser.GeyserImpl;
 import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
-import org.geysermc.geyser.network.GameProtocol;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.EnchantmentData;
-import org.geysermc.geyser.registry.type.ItemMapping;
 
 import java.io.InputStream;
 import java.util.EnumMap;
@@ -77,9 +76,9 @@ public class EnchantmentRegistryLoader implements RegistryLoader<String, Map<Jav
             IntSet validItems = new IntOpenHashSet();
             for (JsonNode itemNode : node.get("valid_items")) {
                 String javaIdentifier = itemNode.textValue();
-                ItemMapping itemMapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping(javaIdentifier);
-                if (itemMapping != null) {
-                    validItems.add(itemMapping.getJavaId());
+                Item item = Registries.JAVA_ITEM_IDENTIFIERS.get(javaIdentifier);
+                if (item != null) {
+                    validItems.add(item.javaId());
                 } else {
                     throw new NullPointerException("No item entry exists for java identifier: " + javaIdentifier);
                 }
diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java
index 246777aed..16fc1f817 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java
@@ -27,6 +27,8 @@ package org.geysermc.geyser.registry.loader;
 
 import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData;
 import org.geysermc.geyser.inventory.item.Potion;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.network.GameProtocol;
 import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
@@ -51,37 +53,37 @@ public class PotionMixRegistryLoader implements RegistryLoader<Object, Set<Potio
     @Override
     public Set<PotionMixData> load(Object input) {
         List<ItemMapping> ingredients = new ArrayList<>();
-        ingredients.add(getNonNull("minecraft:nether_wart"));
-        ingredients.add(getNonNull("minecraft:redstone"));
-        ingredients.add(getNonNull("minecraft:glowstone_dust"));
-        ingredients.add(getNonNull("minecraft:fermented_spider_eye"));
-        ingredients.add(getNonNull("minecraft:gunpowder"));
-        ingredients.add(getNonNull("minecraft:dragon_breath"));
-        ingredients.add(getNonNull("minecraft:sugar"));
-        ingredients.add(getNonNull("minecraft:rabbit_foot"));
-        ingredients.add(getNonNull("minecraft:glistering_melon_slice"));
-        ingredients.add(getNonNull("minecraft:spider_eye"));
-        ingredients.add(getNonNull("minecraft:pufferfish"));
-        ingredients.add(getNonNull("minecraft:magma_cream"));
-        ingredients.add(getNonNull("minecraft:golden_carrot"));
-        ingredients.add(getNonNull("minecraft:blaze_powder"));
-        ingredients.add(getNonNull("minecraft:ghast_tear"));
-        ingredients.add(getNonNull("minecraft:turtle_helmet"));
-        ingredients.add(getNonNull("minecraft:phantom_membrane"));
+        ingredients.add(getNonNull(Items.NETHER_WART));
+        ingredients.add(getNonNull(Items.REDSTONE));
+        ingredients.add(getNonNull(Items.GLOWSTONE_DUST));
+        ingredients.add(getNonNull(Items.FERMENTED_SPIDER_EYE));
+        ingredients.add(getNonNull(Items.GUNPOWDER));
+        ingredients.add(getNonNull(Items.DRAGON_BREATH));
+        ingredients.add(getNonNull(Items.SUGAR));
+        ingredients.add(getNonNull(Items.RABBIT_FOOT));
+        ingredients.add(getNonNull(Items.GLISTERING_MELON_SLICE));
+        ingredients.add(getNonNull(Items.SPIDER_EYE));
+        ingredients.add(getNonNull(Items.PUFFERFISH));
+        ingredients.add(getNonNull(Items.MAGMA_CREAM));
+        ingredients.add(getNonNull(Items.GOLDEN_CARROT));
+        ingredients.add(getNonNull(Items.BLAZE_POWDER));
+        ingredients.add(getNonNull(Items.GHAST_TEAR));
+        ingredients.add(getNonNull(Items.TURTLE_HELMET));
+        ingredients.add(getNonNull(Items.PHANTOM_MEMBRANE));
 
         List<ItemMapping> inputs = new ArrayList<>();
-        inputs.add(getNonNull("minecraft:potion"));
-        inputs.add(getNonNull("minecraft:splash_potion"));
-        inputs.add(getNonNull("minecraft:lingering_potion"));
+        inputs.add(getNonNull(Items.POTION));
+        inputs.add(getNonNull(Items.SPLASH_POTION));
+        inputs.add(getNonNull(Items.LINGERING_POTION));
 
-        ItemMapping glassBottle = getNonNull("minecraft:glass_bottle");
+        ItemMapping glassBottle = getNonNull(Items.GLASS_BOTTLE);
 
         Set<PotionMixData> potionMixes = new HashSet<>();
 
         // Add all types of potions as inputs
         ItemMapping fillerIngredient = ingredients.get(0);
         for (ItemMapping entryInput : inputs) {
-            for (Potion potion : Potion.values()) {
+            for (Potion potion : Potion.VALUES) {
                 potionMixes.add(new PotionMixData(
                         entryInput.getBedrockDefinition().getRuntimeId(), potion.getBedrockId(),
                         fillerIngredient.getBedrockDefinition().getRuntimeId(), fillerIngredient.getBedrockData(),
@@ -102,10 +104,10 @@ public class PotionMixRegistryLoader implements RegistryLoader<Object, Set<Potio
         return potionMixes;
     }
 
-    private static ItemMapping getNonNull(String javaIdentifier) {
-        ItemMapping itemMapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping(javaIdentifier);
+    private static ItemMapping getNonNull(Item javaItem) {
+        ItemMapping itemMapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping(javaItem);
         if (itemMapping == null)
-            throw new NullPointerException("No item entry exists for java identifier: " + javaIdentifier);
+            throw new NullPointerException("No item entry exists for java identifier: " + javaItem.javaIdentifier());
 
         return itemMapping;
     }
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java
index cc67ea88c..5ea76ae66 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java
@@ -54,7 +54,7 @@ public class CreativeItemRegistryPopulator {
             (identifier, data) -> identifier.equals("minecraft:bordure_indented_banner_pattern") || identifier.equals("minecraft:field_masoned_banner_pattern")
     );
 
-    public static void populate(Map.Entry<String, ItemRegistryPopulator.PaletteVersion> version, Map<String, ItemDefinition> definitions, Consumer<ItemData.Builder> itemConsumer) {
+    static void populate(Map.Entry<String, ItemRegistryPopulator.PaletteVersion> version, Map<String, ItemDefinition> definitions, Consumer<ItemData.Builder> itemConsumer) {
         GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
 
         // Load creative items
@@ -79,7 +79,7 @@ public class CreativeItemRegistryPopulator {
     private static ItemData.Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map<String, ItemDefinition> definitions) {
         int count = 1;
         int damage = 0;
-        int bedrockBlockRuntimeId = 0;
+        int bedrockBlockRuntimeId = -1;
         NbtMap tag = null;
         JsonNode damageNode = itemNode.get("damage");
         if (damageNode != null) {
@@ -125,6 +125,6 @@ public class CreativeItemRegistryPopulator {
                 .damage(damage)
                 .count(count)
                 .tag(tag)
-                .blockDefinition(blockMappings.getDefinition(bedrockBlockRuntimeId));
+                .blockDefinition(bedrockBlockRuntimeId == -1 ? null : blockMappings.getDefinition(bedrockBlockRuntimeId));
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java
index 75b74b0a3..84c0905db 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java
@@ -26,12 +26,12 @@
 package org.geysermc.geyser.registry.populator;
 
 import com.google.common.collect.Multimap;
+import org.checkerframework.checker.nullness.qual.NonNull;
 import org.cloudburstmc.nbt.NbtMap;
 import org.cloudburstmc.nbt.NbtMapBuilder;
 import org.cloudburstmc.nbt.NbtType;
-import it.unimi.dsi.fastutil.objects.ObjectArrayList;
-import org.checkerframework.checker.nullness.qual.NonNull;
 import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
+import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
 import org.geysermc.geyser.GeyserImpl;
 import org.geysermc.geyser.api.item.custom.CustomItemData;
@@ -40,9 +40,11 @@ import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
 import org.geysermc.geyser.api.util.TriState;
 import org.geysermc.geyser.event.type.GeyserDefineCustomItemsEventImpl;
 import org.geysermc.geyser.item.GeyserCustomMappingData;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.item.components.ToolBreakSpeedsUtils;
 import org.geysermc.geyser.item.components.WearableSlot;
 import org.geysermc.geyser.item.mappings.MappingsConfigReader;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.GeyserMappingItem;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
@@ -100,7 +102,7 @@ public class CustomItemRegistryPopulator {
     }
 
     public static GeyserCustomMappingData registerCustomItem(String customItemName, GeyserMappingItem javaItem, CustomItemData customItemData, int bedrockId) {
-        ItemDefinition itemDefinition = new ItemDefinition(customItemName, bedrockId, true);
+        ItemDefinition itemDefinition = new SimpleItemDefinition(customItemName, bedrockId, true);
 
         NbtMapBuilder builder = createComponentNbt(customItemData, javaItem, customItemName, bedrockId);
         ComponentItemData componentItemData = new ComponentItemData(customItemName, builder.build());
@@ -129,28 +131,30 @@ public class CustomItemRegistryPopulator {
     public static NonVanillaItemRegistration registerCustomItem(NonVanillaCustomItemData customItemData, int customItemId) {
         String customIdentifier = customItemData.identifier();
 
+        Item.Builder itemBuilder = Item.builder()
+                .stackSize(customItemData.stackSize())
+                .maxDamage(customItemData.maxDamage());
+        Item item = new Item(customIdentifier, itemBuilder);
+        Items.register(item, customItemData.javaId());
+
         ItemMapping customItemMapping = ItemMapping.builder()
-                .javaIdentifier(customIdentifier)
-                .bedrockIdentifier(customIdentifier)
-                .javaId(customItemData.javaId())
-                .bedrockDefinition(new ItemDefinition(customIdentifier, customItemId, true))
+                .bedrockDefinition(new SimpleItemDefinition(customIdentifier, customItemId, true))
                 .bedrockData(0)
                 .bedrockBlockDefinition(null)
-                .stackSize(customItemData.stackSize())
                 .toolType(customItemData.toolType())
                 .toolTier(customItemData.toolTier())
                 .translationString(customItemData.translationString())
-                .maxDamage(customItemData.maxDamage())
                 .repairMaterials(customItemData.repairMaterials())
                 .hasSuspiciousStewEffect(false)
                 .customItemOptions(Collections.emptyList())
+                .javaItem(item)
                 .build();
 
         NbtMapBuilder builder = createComponentNbt(customItemData, customItemData.identifier(), customItemId,
                 customItemData.creativeCategory(), customItemData.creativeGroup(), customItemData.isHat(), customItemData.isTool());
         ComponentItemData componentItemData = new ComponentItemData(customIdentifier, builder.build());
 
-        return new NonVanillaItemRegistration(componentItemData, customItemMapping);
+        return new NonVanillaItemRegistration(componentItemData, item, customItemMapping);
     }
 
     private static NbtMapBuilder createComponentNbt(CustomItemData customItemData, GeyserMappingItem mapping,
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java
index ae6f8abe3..bf2c07a04 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java
@@ -29,23 +29,21 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.MultimapBuilder;
 import it.unimi.dsi.fastutil.Pair;
-import it.unimi.dsi.fastutil.objects.*;
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.cloudburstmc.nbt.NbtType;
-import it.unimi.dsi.fastutil.ints.Int2IntMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
 import it.unimi.dsi.fastutil.ints.IntSet;
+import it.unimi.dsi.fastutil.objects.*;
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.cloudburstmc.nbt.NbtType;
 import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
 import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
-import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
 import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
 import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
+import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
-import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry;
 import org.geysermc.geyser.GeyserBootstrap;
 import org.geysermc.geyser.GeyserImpl;
 import org.geysermc.geyser.api.item.custom.CustomItemData;
@@ -53,11 +51,11 @@ import org.geysermc.geyser.api.item.custom.CustomItemOptions;
 import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
 import org.geysermc.geyser.inventory.item.StoredItemMappings;
 import org.geysermc.geyser.item.GeyserCustomMappingData;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.BlockRegistries;
 import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.*;
-import org.geysermc.geyser.util.ItemUtils;
-import org.geysermc.geyser.util.collection.FixedInt2IntMap;
 
 import java.io.InputStream;
 import java.util.*;
@@ -68,7 +66,7 @@ import java.util.concurrent.atomic.AtomicInteger;
  */
 public class ItemRegistryPopulator {
 
-    record PaletteVersion(int protocolVersion, Map<String, String> additionalTranslatedItems) {
+    record PaletteVersion(int protocolVersion, Map<Item, String> additionalTranslatedItems) {
     }
 
     public static void populate() {
@@ -102,16 +100,11 @@ public class ItemRegistryPopulator {
 
         // We can reduce some operations as Java information is the same across all palette versions
         boolean firstMappingsPass = true;
-        Int2IntMap dyeColors = new FixedInt2IntMap();
 
         /* Load item palette */
         for (Map.Entry<String, PaletteVersion> palette : paletteVersions.entrySet()) {
             TypeReference<List<PaletteItem>> paletteEntriesType = new TypeReference<>() {};
 
-            // Used to get the Bedrock namespaced ID (in instances where there are small differences)
-
-            List<String> itemNames = new ArrayList<>();
-
             List<PaletteItem> itemEntries;
             try (InputStream stream = bootstrap.getResource(String.format("bedrock/runtime_item_states.%s.json", palette.getKey()))) {
                 itemEntries = GeyserImpl.JSON_MAPPER.readValue(stream, paletteEntriesType);
@@ -123,7 +116,7 @@ public class ItemRegistryPopulator {
             int nextFreeBedrockId = 0;
             List<ComponentItemData> componentItemData = new ObjectArrayList<>();
 
-            SimpleDefinitionRegistry.Builder<ItemDefinition> registry = SimpleDefinitionRegistry.builder();
+            Int2ObjectMap<ItemDefinition> registry = new Int2ObjectOpenHashMap<>();
             Map<String, ItemDefinition> definitions = new Object2ObjectLinkedOpenHashMap<>();
 
             for (PaletteItem entry : itemEntries) {
@@ -132,9 +125,9 @@ public class ItemRegistryPopulator {
                     nextFreeBedrockId = id + 1;
                 }
 
-                ItemDefinition definition = new ItemDefinition(entry.getName(), id, false);
+                ItemDefinition definition = new SimpleItemDefinition(entry.getName().intern(), id, false);
                 definitions.put(entry.getName(), definition);
-                registry.add(definition);
+                registry.put(definition.getRuntimeId(), definition);
             }
 
             Object2ObjectMap<String, BlockDefinition> bedrockBlockIdOverrides = new Object2ObjectOpenHashMap<>();
@@ -142,12 +135,11 @@ public class ItemRegistryPopulator {
 
             List<ItemDefinition> boats = new ObjectArrayList<>();
             List<ItemDefinition> buckets = new ObjectArrayList<>();
-            List<ItemDefinition> spawnEggs = new ObjectArrayList<>();
             List<ItemData> carpets = new ObjectArrayList<>();
 
             List<ItemMapping> mappings = new ObjectArrayList<>();
             // Temporary mapping to create stored items
-            Map<String, ItemMapping> javaIdentifierToMapping = new Object2ObjectOpenHashMap<>();
+            Map<Item, ItemMapping> javaItemToMapping = new Object2ObjectOpenHashMap<>();
 
             List<ItemData> creativeItems = new ArrayList<>();
 
@@ -175,14 +167,11 @@ public class ItemRegistryPopulator {
 
             BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.getValue().protocolVersion());
 
-            int itemIndex = 0;
-            int javaFurnaceMinecartId = 0;
-
-            Set<String> javaOnlyItems = new ObjectOpenHashSet<>();
-            Collections.addAll(javaOnlyItems, "minecraft:spectral_arrow", "minecraft:debug_stick",
-                    "minecraft:knowledge_book", "minecraft:tipped_arrow", "minecraft:bundle");
+            Set<Item> javaOnlyItems = new ObjectOpenHashSet<>();
+            Collections.addAll(javaOnlyItems, Items.SPECTRAL_ARROW, Items.DEBUG_STICK,
+                    Items.KNOWLEDGE_BOOK, Items.TIPPED_ARROW, Items.BUNDLE);
             if (!customItemsAllowed) {
-                javaOnlyItems.add("minecraft:furnace_minecart");
+                javaOnlyItems.add(Items.FURNACE_MINECART);
             }
             // Java-only items for this version
             javaOnlyItems.addAll(palette.getValue().additionalTranslatedItems().keySet());
@@ -191,9 +180,12 @@ public class ItemRegistryPopulator {
             Set<String> registeredItemNames = new ObjectOpenHashSet<>(); // This is used to check for duplicate item names
 
             for (Map.Entry<String, GeyserMappingItem> entry : items.entrySet()) {
-                String javaIdentifier = entry.getKey().intern();
+                Item javaItem = Registries.JAVA_ITEM_IDENTIFIERS.get(entry.getKey());
+                if (javaItem == null) {
+                    throw new RuntimeException("Extra item in mappings? " + entry.getKey());
+                }
                 GeyserMappingItem mappingItem;
-                String replacementItem = palette.getValue().additionalTranslatedItems().get(javaIdentifier);
+                String replacementItem = palette.getValue().additionalTranslatedItems().get(javaItem);
                 if (replacementItem != null) {
                     mappingItem = items.get(replacementItem);
                 } else {
@@ -201,9 +193,7 @@ public class ItemRegistryPopulator {
                     mappingItem = entry.getValue();
                 }
 
-                if (customItemsAllowed && javaIdentifier.equals("minecraft:furnace_minecart")) {
-                    javaFurnaceMinecartId = itemIndex;
-                    itemIndex++;
+                if (customItemsAllowed && javaItem == Items.FURNACE_MINECART) {
                     // Will be added later
                     mappings.add(null);
                     continue;
@@ -215,8 +205,6 @@ public class ItemRegistryPopulator {
                     throw new RuntimeException("Missing Bedrock ItemDefinition in mappings: " + bedrockIdentifier);
                 }
 
-                int stackSize = mappingItem.getStackSize();
-
                 BlockDefinition bedrockBlock = null;
                 Integer firstBlockRuntimeId = entry.getValue().getFirstBlockRuntimeId();
                 if (firstBlockRuntimeId != null) {
@@ -336,15 +324,12 @@ public class ItemRegistryPopulator {
                 }
 
                 ItemMapping.ItemMappingBuilder mappingBuilder = ItemMapping.builder()
-                        .javaIdentifier(javaIdentifier)
-                        .javaId(itemIndex)
                         .bedrockIdentifier(bedrockIdentifier.intern())
                         .bedrockDefinition(definition)
                         .bedrockData(mappingItem.getBedrockData())
                         .bedrockBlockDefinition(bedrockBlock)
-                        .stackSize(stackSize)
-                        .maxDamage(mappingItem.getMaxDamage())
-                        .hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect());
+                        .hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect())
+                        .javaItem(javaItem);
 
                 if (mappingItem.getRepairMaterials() != null) {
                     mappingBuilder = mappingBuilder.repairMaterials(new ObjectOpenHashSet<>(mappingItem.getRepairMaterials()));
@@ -360,7 +345,7 @@ public class ItemRegistryPopulator {
                     }
                 }
 
-                if (javaOnlyItems.contains(javaIdentifier)) {
+                if (javaOnlyItems.contains(javaItem)) {
                     // These items don't exist on Bedrock, so set up a variable that indicates they should have custom names
                     mappingBuilder = mappingBuilder.translationString((bedrockBlock != null ? "block." : "item.") + entry.getKey().replace(":", "."));
                     GeyserImpl.getInstance().getLogger().debug("Adding " + entry.getKey() + " as an item that needs to be translated.");
@@ -368,7 +353,7 @@ public class ItemRegistryPopulator {
 
                 // Add the custom item properties, if applicable
                 List<Pair<CustomItemOptions, ItemDefinition>> customItemOptions;
-                Collection<CustomItemData> customItemsToLoad = customItems.get(javaIdentifier);
+                Collection<CustomItemData> customItemsToLoad = customItems.get(javaItem.javaIdentifier());
                 if (customItemsAllowed && !customItemsToLoad.isEmpty()) {
                     customItemOptions = new ObjectArrayList<>(customItemsToLoad.size());
 
@@ -386,9 +371,6 @@ public class ItemRegistryPopulator {
                         GeyserCustomMappingData customMapping = CustomItemRegistryPopulator.registerCustomItem(
                                 customItemName, mappingItem, customItem, customProtocolId
                         );
-                        // StartGamePacket entry - needed for Bedrock to recognize the item through the protocol
-                        definitions.put(customMapping.stringId(), customMapping.itemDefinition());
-                        registry.add(customMapping.itemDefinition());
                         // ComponentItemData - used to register some custom properties
                         componentItemData.add(customMapping.componentItemData());
                         customItemOptions.add(Pair.of(customItem.customItemOptions(), customMapping.itemDefinition()));
@@ -405,6 +387,7 @@ public class ItemRegistryPopulator {
 
                 ItemMapping mapping = mappingBuilder.build();
 
+                /*
                 if (javaIdentifier.contains("boat")) {
                     boats.add(definition);
                 } else if (javaIdentifier.contains("bucket") && !javaIdentifier.contains("milk")) {
@@ -419,26 +402,15 @@ public class ItemRegistryPopulator {
                             .build());
                 } else if (javaIdentifier.startsWith("minecraft:music_disc_")) {
                     // The Java record level event uses the item ID as the "key" to play the record
-                    Registries.RECORDS.register(itemIndex, SoundEvent.valueOf("RECORD_" +
+                    Registries.RECORDS.register(javaItem.javaId(), SoundEvent.valueOf("RECORD_" +
                             javaIdentifier.replace("minecraft:music_disc_", "").toUpperCase(Locale.ENGLISH)));
-                } else if (javaIdentifier.endsWith("_spawn_egg")) {
-                    spawnEggs.add(definition);
                 }
+                */
 
                 mappings.add(mapping);
-                javaIdentifierToMapping.put(javaIdentifier, mapping);
-
-                itemNames.add(javaIdentifier);
-
-                if (firstMappingsPass && mappingItem.getDyeColor() != -1) {
-                    dyeColors.put(itemIndex, mappingItem.getDyeColor());
-                }
-
-                itemIndex++;
+                javaItemToMapping.put(javaItem, mapping);
             }
 
-            itemNames.add("minecraft:furnace_minecart");
-
             ItemDefinition lodestoneCompass = definitions.get("minecraft:lodestone_compass");
             if (lodestoneCompass == null) {
                 throw new RuntimeException("Lodestone compass not found in item palette!");
@@ -446,30 +418,26 @@ public class ItemRegistryPopulator {
 
             // Add the lodestone compass since it doesn't exist on java but we need it for item conversion
             ItemMapping lodestoneEntry = ItemMapping.builder()
-                    .javaIdentifier("")
+                    .javaItem(Items.COMPASS)
                     .bedrockIdentifier("minecraft:lodestone_compass")
-                    .javaId(-1)
                     .bedrockDefinition(lodestoneCompass)
                     .bedrockData(0)
                     .bedrockBlockDefinition(null)
-                    .stackSize(1)
                     .customItemOptions(Collections.emptyList())
                     .build();
 
             if (customItemsAllowed) {
                 // Add furnace minecart
-                ItemDefinition definition = new ItemDefinition("geysermc:furnace_minecart", nextFreeBedrockId, true);
+                ItemDefinition definition = new SimpleItemDefinition("geysermc:furnace_minecart", nextFreeBedrockId, true);
                 definitions.put("geysermc:furnace_minecart", definition);
-                registry.add(definition);
+                registry.put(definition.getRuntimeId(), definition);
 
-                mappings.set(javaFurnaceMinecartId, ItemMapping.builder()
-                        .javaIdentifier("minecraft:furnace_minecart")
+                mappings.set(Items.FURNACE_MINECART.javaId(), ItemMapping.builder()
+                        .javaItem(Items.FURNACE_MINECART)
                         .bedrockIdentifier("geysermc:furnace_minecart")
-                        .javaId(javaFurnaceMinecartId)
                         .bedrockDefinition(definition)
                         .bedrockData(0)
                         .bedrockBlockDefinition(null)
-                        .stackSize(1)
                         .customItemOptions(Collections.emptyList()) // TODO check for custom items with furnace minecart
                         .build());
 
@@ -496,11 +464,12 @@ public class ItemRegistryPopulator {
 
                     componentItemData.add(registration.componentItemData());
                     ItemMapping mapping = registration.mapping();
-                    while (mapping.getJavaId() >= mappings.size()) {
+                    Item javaItem = registration.javaItem();
+                    while (javaItem.javaId() >= mappings.size()) {
                         // Fill with empty to get to the correct size
                         mappings.add(ItemMapping.AIR);
                     }
-                    mappings.set(mapping.getJavaId(), mapping);
+                    mappings.set(javaItem.javaId(), mapping);
 
                     if (customItem.creativeGroup() != null || customItem.creativeCategory().isPresent()) {
                         creativeItems.add(ItemData.builder()
@@ -515,14 +484,11 @@ public class ItemRegistryPopulator {
             ItemMappings itemMappings = ItemMappings.builder()
                     .items(mappings.toArray(new ItemMapping[0]))
                     .creativeItems(creativeItems.toArray(new ItemData[0]))
-                    .definitionRegistry(registry.build())
-                    .itemDefinitions(List.copyOf(definitions.values()))
-                    .itemNames(itemNames.toArray(new String[0]))
-                    .storedItems(new StoredItemMappings(javaIdentifierToMapping))
+                    .itemDefinitions(registry)
+                    .storedItems(new StoredItemMappings(javaItemToMapping))
                     .javaOnlyItems(javaOnlyItems)
                     .buckets(buckets)
                     .boats(boats)
-                    .spawnEggs(spawnEggs)
                     .carpets(carpets)
                     .componentItemData(componentItemData)
                     .lodestoneCompass(lodestoneEntry)
@@ -533,8 +499,6 @@ public class ItemRegistryPopulator {
 
             firstMappingsPass = false;
         }
-
-        ItemUtils.setDyeColors(dyeColors);
     }
 
     private static void registerFurnaceMinecart(int nextFreeBedrockId, List<ComponentItemData> componentItemData) {
diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserItemDefinition.java b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserItemDefinition.java
new file mode 100644
index 000000000..c8d83b021
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserItemDefinition.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.registry.type;
+
+import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
+import org.geysermc.geyser.item.type.Item;
+
+/**
+ * Implements ItemDefinition while also providing a reference to our item mappings.
+ */
+public record GeyserItemDefinition(Item javaItem, String identifier, boolean componentBased, int runtimeId) implements ItemDefinition {
+    @Override
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    @Override
+    public boolean isComponentBased() {
+        return componentBased;
+    }
+
+    @Override
+    public int getRuntimeId() {
+        return runtimeId;
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMapping.java b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMapping.java
index caa940b28..278e0aca9 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMapping.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMapping.java
@@ -26,13 +26,13 @@
 package org.geysermc.geyser.registry.type;
 
 import it.unimi.dsi.fastutil.Pair;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Value;
+import lombok.*;
 import org.checkerframework.checker.nullness.qual.NonNull;
 import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
 import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
 import org.geysermc.geyser.api.item.custom.CustomItemOptions;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 
 import java.util.Collections;
 import java.util.List;
@@ -44,24 +44,19 @@ import java.util.Set;
 public class ItemMapping {
     public static final ItemMapping AIR = new ItemMapping(
             "minecraft:air",
-            "minecraft:air",
-            0,
             ItemDefinition.AIR,
             0,
             null, // Air is never sent in full over the network for this to serialize.
-            64,
             null,
             null,
-            null
-            , Collections.emptyList(),
-            0,
             null,
-            false
+            Collections.emptyList(),
+            null,
+            false,
+            Items.AIR
     );
 
-    String javaIdentifier;
     String bedrockIdentifier;
-    int javaId;
     ItemDefinition bedrockDefinition;
     int bedrockData;
 
@@ -70,7 +65,6 @@ public class ItemMapping {
      * Required since 1.16.220.
      */
     BlockDefinition bedrockBlockDefinition;
-    int stackSize;
 
     String toolType;
     String toolTier;
@@ -80,12 +74,13 @@ public class ItemMapping {
     @NonNull
     List<Pair<CustomItemOptions, ItemDefinition>> customItemOptions;
 
-    int maxDamage;
-
     Set<String> repairMaterials;
 
     boolean hasSuspiciousStewEffect;
 
+    @NonNull
+    Item javaItem;
+
     /**
      * Gets if this item is a block.
      *
diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java
index 8fa7d9f91..77564e98b 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java
@@ -35,6 +35,9 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import org.cloudburstmc.protocol.common.DefinitionRegistry;
 import org.geysermc.geyser.GeyserImpl;
 import org.geysermc.geyser.inventory.item.StoredItemMappings;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
+import org.geysermc.geyser.item.type.PotionItem;
 
 import javax.annotation.Nonnull;
 import java.util.List;
@@ -44,7 +47,7 @@ import java.util.WeakHashMap;
 
 @Builder
 @Value
-public class ItemMappings {
+public class ItemMappings implements DefinitionRegistry<ItemDefinition> {
 
     Map<String, ItemMapping> cachedJavaMappings = new WeakHashMap<>();
 
@@ -56,16 +59,13 @@ public class ItemMappings {
     ItemMapping lodestoneCompass;
 
     ItemData[] creativeItems;
-    List<ItemDefinition> itemDefinitions;
-    DefinitionRegistry<ItemDefinition> definitionRegistry;
+    Int2ObjectMap<ItemDefinition> itemDefinitions;
 
     StoredItemMappings storedItems;
-    String[] itemNames;
-    Set<String> javaOnlyItems;
+    Set<Item> javaOnlyItems;
 
     List<ItemDefinition> buckets;
     List<ItemDefinition> boats;
-    List<ItemDefinition> spawnEggs;
     List<ItemData> carpets;
 
     List<ComponentItemData> componentItemData;
@@ -94,6 +94,10 @@ public class ItemMappings {
         return javaId >= 0 && javaId < this.items.length ? this.items[javaId] : ItemMapping.AIR;
     }
 
+    public ItemMapping getMapping(Item javaItem) {
+        return getMapping(javaItem.javaIdentifier());
+    }
+
     /**
      * Gets an {@link ItemMapping} from the given Minecraft: Java Edition
      * block state identifier.
@@ -104,7 +108,7 @@ public class ItemMappings {
     public ItemMapping getMapping(String javaIdentifier) {
         return this.cachedJavaMappings.computeIfAbsent(javaIdentifier, key -> {
             for (ItemMapping mapping : this.items) {
-                if (mapping.getJavaIdentifier().equals(key)) {
+                if (mapping.getJavaItem().javaIdentifier().equals(key)) {
                     return mapping;
                 }
             }
@@ -120,10 +124,9 @@ public class ItemMappings {
      */
     public ItemMapping getMapping(ItemData data) {
         ItemDefinition definition = data.getDefinition();
-        int id = data.getDefinition().getRuntimeId();
         if (ItemDefinition.AIR.equals(definition)) {
             return ItemMapping.AIR;
-        } else if (definition.equals(lodestoneCompass.getBedrockDefinition())) {
+        } else if (definition.getRuntimeId() == lodestoneCompass.getBedrockDefinition().getRuntimeId()) {
             return lodestoneCompass;
         }
 
@@ -131,7 +134,7 @@ public class ItemMappings {
         boolean hasDamage = data.getDamage() != 0;
 
         for (ItemMapping mapping : this.items) {
-            if (mapping.getBedrockDefinition().equals(definition)) {
+            if (mapping.getBedrockDefinition().getRuntimeId() == definition.getRuntimeId()) {
                 if (isBlock && !hasDamage) { // Pre-1.16.220 will not use block runtime IDs at all, so we shouldn't check either
                     if (data.getBlockDefinition() != mapping.getBedrockBlockDefinition()) {
                         continue;
@@ -139,22 +142,29 @@ public class ItemMappings {
                 } else {
                     if (!(mapping.getBedrockData() == data.getDamage() ||
                             // Make exceptions for potions, tipped arrows, firework stars, and goat horns, whose damage values can vary
-                            (mapping.getJavaIdentifier().endsWith("potion") || mapping.getJavaIdentifier().equals("minecraft:arrow")
-                                    || mapping.getJavaIdentifier().equals("minecraft:firework_star") || mapping.getJavaIdentifier().equals("minecraft:goat_horn")))) {
+                            (mapping.getJavaItem() instanceof PotionItem || mapping.getJavaItem() == Items.ARROW
+                                    || mapping.getJavaItem() == Items.FIREWORK_STAR || mapping.getJavaItem() == Items.GOAT_HORN))) {
                         continue;
                     }
                 }
-                if (!this.javaOnlyItems.contains(mapping.getJavaIdentifier())) {
+                if (!this.javaOnlyItems.contains(mapping.getJavaItem())) {
                     // From a Bedrock item data, we aren't getting one of these items
                     return mapping;
                 }
             }
         }
 
-        // This will hide the message when the player clicks with an empty hand
-        if (id != 0 && data.getDamage() != 0) {
-            GeyserImpl.getInstance().getLogger().debug("Missing mapping for bedrock item " + data.getDefinition() + ":" + data.getDamage());
-        }
+        GeyserImpl.getInstance().getLogger().debug("Missing mapping for bedrock item " + data);
         return ItemMapping.AIR;
     }
+
+    @Override
+    public ItemDefinition getDefinition(int bedrockId) {
+        return this.itemDefinitions.get(bedrockId);
+    }
+
+    @Override
+    public boolean isRegistered(ItemDefinition definition) {
+        return getDefinition(definition.getRuntimeId()) == definition;
+    }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/NonVanillaItemRegistration.java b/core/src/main/java/org/geysermc/geyser/registry/type/NonVanillaItemRegistration.java
index 562c8a6bb..16ac51749 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/type/NonVanillaItemRegistration.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/type/NonVanillaItemRegistration.java
@@ -26,9 +26,10 @@
 package org.geysermc.geyser.registry.type;
 
 import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
+import org.geysermc.geyser.item.type.Item;
 
 /**
  * The return data of a successful registration of a custom item.
  */
-public record NonVanillaItemRegistration(ComponentItemData componentItemData, ItemMapping mapping) {
+public record NonVanillaItemRegistration(ComponentItemData componentItemData, Item javaItem, ItemMapping mapping) {
 }
\ No newline at end of file
diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
index ffd3ff209..d1e82fb0e 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -116,13 +116,13 @@ import org.geysermc.geyser.inventory.Inventory;
 import org.geysermc.geyser.inventory.PlayerInventory;
 import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
 import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.level.JavaDimension;
 import org.geysermc.geyser.level.WorldManager;
 import org.geysermc.geyser.level.physics.CollisionManager;
 import org.geysermc.geyser.network.netty.LocalSession;
 import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.BlockMappings;
-import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.registry.type.ItemMappings;
 import org.geysermc.geyser.session.auth.AuthData;
 import org.geysermc.geyser.session.auth.BedrockClientData;
@@ -1278,12 +1278,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
      * blocking and sends a packet to the Java server.
      */
     private boolean attemptToBlock() {
-        ItemMapping shield = itemMappings.getStoredItems().shield();
-
         ServerboundUseItemPacket useItemPacket;
-        if (playerInventory.getItemInHand().getJavaId() == shield.getJavaId()) {
+        if (playerInventory.getItemInHand().asItem() == Items.SHIELD) {
             useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, worldCache.nextPredictionSequence());
-        } else if (playerInventory.getOffhand().getJavaId() == shield.getJavaId()) {
+        } else if (playerInventory.getOffhand().asItem() == Items.SHIELD) {
             useItemPacket = new ServerboundUseItemPacket(Hand.OFF_HAND, worldCache.nextPredictionSequence());
         } else {
             // No blocking
@@ -1410,7 +1408,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
     }
 
     private void startGame() {
-        this.upstream.getCodecHelper().setItemDefinitions(this.itemMappings.getDefinitionRegistry());
+        this.upstream.getCodecHelper().setItemDefinitions(this.itemMappings);
         this.upstream.getCodecHelper().setBlockDefinitions((DefinitionRegistry) this.blockMappings); //FIXME
 
         StartGamePacket startGamePacket = new StartGamePacket();
@@ -1467,7 +1465,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
         startGamePacket.setEnchantmentSeed(0);
         startGamePacket.setMultiplayerCorrelationId("");
 
-        startGamePacket.setItemDefinitions(this.itemMappings.getItemDefinitions());
+        startGamePacket.setItemDefinitions(this.itemMappings.getItemDefinitions().values().stream().toList()); // TODO
         // startGamePacket.setBlockPalette(this.blockMappings.getBedrockBlockPalette());
 
         startGamePacket.setVanillaVersion("*");
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java
index e3ffa301e..5cd112a5f 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/BookEditCache.java
@@ -28,6 +28,7 @@ package org.geysermc.geyser.session.cache;
 import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundEditBookPacket;
 import lombok.Setter;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 
 /**
@@ -63,7 +64,7 @@ public class BookEditCache {
         }
         // Don't send the update if the player isn't not holding a book, shouldn't happen if we catch all interactions
         GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand();
-        if (itemStack == null || itemStack.getJavaId() != this.session.getItemMappings().getStoredItems().writableBook().getJavaId()) {
+        if (itemStack == null || itemStack.asItem() != Items.WRITABLE_BOOK) {
             packet = null;
             return;
         }
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
index 9cd5b2ef6..89a91ce46 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
@@ -30,8 +30,8 @@ import it.unimi.dsi.fastutil.ints.IntList;
 import it.unimi.dsi.fastutil.ints.IntLists;
 import org.geysermc.geyser.GeyserLogger;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.BlockMapping;
-import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 
 import javax.annotation.ParametersAreNonnullByDefault;
@@ -129,24 +129,24 @@ public class TagCache {
         this.smallFlowers = IntLists.emptyList();
     }
 
-    public boolean isAxolotlTemptItem(ItemMapping itemMapping) {
-        return axolotlTemptItems.contains(itemMapping.getJavaId());
+    public boolean isAxolotlTemptItem(Item item) {
+        return axolotlTemptItems.contains(item.javaId());
     }
 
     public boolean isFish(GeyserItemStack itemStack) {
         return fishes.contains(itemStack.getJavaId());
     }
 
-    public boolean isFlower(ItemMapping mapping) {
-        return flowers.contains(mapping.getJavaId());
+    public boolean isFlower(Item item) {
+        return flowers.contains(item.javaId());
     }
 
-    public boolean isFoxFood(ItemMapping mapping) {
-        return foxFood.contains(mapping.getJavaId());
+    public boolean isFoxFood(Item item) {
+        return foxFood.contains(item.javaId());
     }
 
-    public boolean shouldPiglinAdmire(ItemMapping mapping) {
-        return piglinLoved.contains(mapping.getJavaId());
+    public boolean shouldPiglinAdmire(Item item) {
+        return piglinLoved.contains(item.javaId());
     }
 
     public boolean isSmallFlower(GeyserItemStack itemStack) {
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java
index 888ce26fe..95f227ed7 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java
@@ -30,6 +30,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
 import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
 import org.geysermc.geyser.inventory.*;
 import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 
 public class CartographyInventoryTranslator extends AbstractBlockInventoryTranslator {
@@ -43,11 +44,11 @@ public class CartographyInventoryTranslator extends AbstractBlockInventoryTransl
         if (javaDestinationSlot == 0) {
             // Bedrock Edition can use paper or an empty map in slot 0
             GeyserItemStack itemStack = javaSourceSlot == -1 ? session.getPlayerInventory().getCursor() : inventory.getItem(javaSourceSlot);
-            return itemStack.getMapping(session).getJavaIdentifier().equals("minecraft:paper") || itemStack.getMapping(session).getJavaIdentifier().equals("minecraft:map");
+            return itemStack.asItem() == Items.PAPER || itemStack.asItem() == Items.MAP;
         } else if (javaDestinationSlot == 1) {
             // Bedrock Edition can use a compass to create locator maps, or use a filled map, in the ADDITIONAL slot
             GeyserItemStack itemStack = javaSourceSlot == -1 ? session.getPlayerInventory().getCursor() : inventory.getItem(javaSourceSlot);
-            return itemStack.getMapping(session).getJavaIdentifier().equals("minecraft:compass") || itemStack.getMapping(session).getJavaIdentifier().equals("minecraft:filled_map");
+            return itemStack.asItem() == Items.COMPASS || itemStack.asItem() == Items.FILLED_MAP;
         }
         return false;
     }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java
index f54bb271b..c61ff13de 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java
@@ -854,7 +854,7 @@ public abstract class InventoryTranslator {
             int slot = it.nextInt();
             BedrockContainerSlot bedrockSlot = javaSlotToBedrockContainer(slot);
             List<ItemStackResponseSlot> list = containerMap.computeIfAbsent(bedrockSlot.container(), k -> new ArrayList<>());
-            list.add(makeItemEntry(session, bedrockSlot.slot(), inventory.getItem(slot)));
+            list.add(makeItemEntry(bedrockSlot.slot(), inventory.getItem(slot)));
         }
 
         List<ItemStackResponseContainer> containerEntries = new ArrayList<>();
@@ -862,13 +862,13 @@ public abstract class InventoryTranslator {
             containerEntries.add(new ItemStackResponseContainer(entry.getKey(), entry.getValue()));
         }
 
-        ItemStackResponseSlot cursorEntry = makeItemEntry(session, 0, session.getPlayerInventory().getCursor());
+        ItemStackResponseSlot cursorEntry = makeItemEntry(0, session.getPlayerInventory().getCursor());
         containerEntries.add(new ItemStackResponseContainer(ContainerSlotType.CURSOR, Collections.singletonList(cursorEntry)));
 
         return containerEntries;
     }
 
-    private static ItemStackResponseSlot makeItemEntry(GeyserSession session, int bedrockSlot, GeyserItemStack itemStack) {
+    private static ItemStackResponseSlot makeItemEntry(int bedrockSlot, GeyserItemStack itemStack) {
         ItemStackResponseSlot itemEntry;
         if (!itemStack.isEmpty()) {
             // As of 1.16.210: Bedrock needs confirmation on what the current item durability is.
@@ -877,7 +877,7 @@ public abstract class InventoryTranslator {
             if (itemStack.getNbt() != null) {
                 Tag damage = itemStack.getNbt().get("Damage");
                 if (damage instanceof IntTag) {
-                    durability = ItemUtils.getCorrectBedrockDurability(session, itemStack.getJavaId(), ((IntTag) damage).getValue());
+                    durability = ItemUtils.getCorrectBedrockDurability(itemStack.asItem(), ((IntTag) damage).getValue());
                 }
             }
 
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java
index 325de5bab..ed0eaaa13 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java
@@ -46,6 +46,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
 import org.geysermc.geyser.inventory.Inventory;
 import org.geysermc.geyser.inventory.SlotType;
 import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
+import org.geysermc.geyser.item.type.DyeItem;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.nbt.BannerTranslator;
 
@@ -113,7 +114,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
         }
 
         // Reject the item if Bedrock is attempting to put in a dye that is not a dye in Java Edition
-        return !itemStack.getMapping(session).getJavaIdentifier().endsWith("_dye");
+        return !(itemStack.asItem() instanceof DyeItem);
     }
 
     @Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java
index 2a17e210c..2bfc9a18b 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java
@@ -48,6 +48,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemS
 import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
 import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
 import org.geysermc.geyser.inventory.*;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.skin.FakeHeadProvider;
 import org.geysermc.geyser.text.GeyserLocale;
@@ -134,7 +135,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
 
         if (slot == 5) {
             // Check for custom skull
-            if (javaItem.getJavaId() == session.getItemMappings().getStoredItems().playerHead().getJavaId()
+            if (javaItem.asItem() == Items.PLAYER_HEAD
                     && javaItem.getNbt() != null
                     && javaItem.getNbt().get("SkullOwner") instanceof CompoundTag profile) {
                 FakeHeadProvider.setHead(session, session.getPlayerEntity(), profile);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java
index 3839b37b5..ab08a5eaf 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CustomItemTranslator.java
@@ -29,7 +29,6 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.IntTag;
 import com.github.steveice10.opennbt.tag.builtin.Tag;
 import it.unimi.dsi.fastutil.Pair;
-import it.unimi.dsi.fastutil.objects.ObjectIntPair;
 import org.checkerframework.checker.nullness.qual.Nullable;
 import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
 import org.geysermc.geyser.api.item.custom.CustomItemOptions;
@@ -55,7 +54,7 @@ final class CustomItemTranslator {
         }
 
         int customModelData = nbt.get("CustomModelData") instanceof IntTag customModelDataTag ? customModelDataTag.getValue() : 0;
-        boolean checkDamage = mapping.getMaxDamage() > 0;
+        boolean checkDamage = mapping.getJavaItem().maxDamage() > 0;
         int damage = !checkDamage ? 0 : nbt.get("Damage") instanceof IntTag damageTag ? damageTag.getValue() : 0;
         boolean unbreakable = checkDamage && !isDamaged(nbt, damage);
 
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java
index b69e00ad7..4277665fc 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java
@@ -25,55 +25,41 @@
 
 package org.geysermc.geyser.translator.inventory.item;
 
+import com.github.steveice10.mc.protocol.data.game.Identifier;
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
-import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag;
-import com.github.steveice10.opennbt.tag.builtin.ByteTag;
-import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
-import com.github.steveice10.opennbt.tag.builtin.DoubleTag;
-import com.github.steveice10.opennbt.tag.builtin.FloatTag;
-import com.github.steveice10.opennbt.tag.builtin.IntArrayTag;
-import com.github.steveice10.opennbt.tag.builtin.IntTag;
-import com.github.steveice10.opennbt.tag.builtin.ListTag;
-import com.github.steveice10.opennbt.tag.builtin.LongArrayTag;
-import com.github.steveice10.opennbt.tag.builtin.LongTag;
-import com.github.steveice10.opennbt.tag.builtin.ShortTag;
-import com.github.steveice10.opennbt.tag.builtin.StringTag;
-import com.github.steveice10.opennbt.tag.builtin.Tag;
+import com.github.steveice10.opennbt.tag.builtin.*;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import org.checkerframework.checker.nullness.qual.NonNull;
 import org.cloudburstmc.nbt.NbtList;
 import org.cloudburstmc.nbt.NbtMap;
 import org.cloudburstmc.nbt.NbtMapBuilder;
 import org.cloudburstmc.nbt.NbtType;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.format.NamedTextColor;
-import org.checkerframework.checker.nullness.qual.NonNull;
 import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import org.geysermc.geyser.GeyserImpl;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.BlockRegistries;
+import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.registry.type.ItemMappings;
 import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.text.ChatColor;
 import org.geysermc.geyser.text.MinecraftLocale;
 import org.geysermc.geyser.translator.text.MessageTranslator;
 import org.geysermc.geyser.util.FileUtils;
 
 import javax.annotation.Nonnull;
 import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
-public abstract class ItemTranslator {
-    private static final Int2ObjectMap<ItemTranslator> ITEM_STACK_TRANSLATORS = new Int2ObjectOpenHashMap<>();
+public final class ItemTranslator {
     private static final List<NbtItemStackTranslator> NBT_TRANSLATORS;
 
-    protected ItemTranslator() {
+    private ItemTranslator() {
     }
 
     public static void init() {
@@ -92,19 +78,6 @@ public abstract class ItemTranslator {
                 if (NbtItemStackTranslator.class.isAssignableFrom(clazz)) {
                     NbtItemStackTranslator nbtItemTranslator = (NbtItemStackTranslator) clazz.getDeclaredConstructor().newInstance();
                     loadedNbtItemTranslators.put(nbtItemTranslator, priority);
-                    continue;
-                }
-                ItemTranslator itemStackTranslator = (ItemTranslator) clazz.getDeclaredConstructor().newInstance();
-                List<ItemMapping> appliedItems = itemStackTranslator.getAppliedItems();
-                for (ItemMapping item : appliedItems) {
-                    ItemTranslator registered = ITEM_STACK_TRANSLATORS.get(item.getJavaId());
-                    if (registered != null) {
-                        GeyserImpl.getInstance().getLogger().error("Could not instantiate annotated item translator " +
-                                clazz.getCanonicalName() + ". Item translator " + registered.getClass().getCanonicalName() +
-                                " is already registered for the item " + item.getJavaIdentifier());
-                        continue;
-                    }
-                    ITEM_STACK_TRANSLATORS.put(item.getJavaId(), itemStackTranslator);
                 }
             } catch (InstantiationException | InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
                 GeyserImpl.getInstance().getLogger().error("Could not instantiate annotated item translator " + clazz.getCanonicalName());
@@ -123,20 +96,15 @@ public abstract class ItemTranslator {
             return new ItemStack(0);
         }
 
-        ItemMapping javaItem = mappings.getMapping(data);
+        ItemMapping bedrockItem = mappings.getMapping(data);
+        Item javaItem = bedrockItem.getJavaItem();
 
-        ItemStack itemStack;
-        ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.get(javaItem.getJavaId());
-        if (itemStackTranslator != null) {
-            itemStack = itemStackTranslator.translateToJava(data, javaItem, mappings);
-        } else {
-            itemStack = DEFAULT_TRANSLATOR.translateToJava(data, javaItem, mappings);
-        }
+        ItemStack itemStack = javaItem.translateToJava(data, bedrockItem, mappings);
 
         if (itemStack != null && itemStack.getNbt() != null) {
             for (NbtItemStackTranslator translator : NBT_TRANSLATORS) {
                 if (translator.acceptItem(javaItem)) {
-                    translator.translateToJava(itemStack.getNbt(), javaItem);
+                    translator.translateToJava(itemStack.getNbt(), bedrockItem);
                 }
             }
             if (itemStack.getNbt().isEmpty()) {
@@ -154,7 +122,7 @@ public abstract class ItemTranslator {
             session.getGeyser().getLogger().debug("ItemMapping returned air: " + javaId);
             return ItemData.builder();
         }
-        return translateToBedrock(session, bedrockItem, count, tag);
+        return translateToBedrock(session, Registries.JAVA_ITEMS.get().get(javaId), bedrockItem, count, tag);
     }
 
     @Nonnull
@@ -168,39 +136,39 @@ public abstract class ItemTranslator {
             session.getGeyser().getLogger().debug("ItemMapping returned air: " + stack);
             return ItemData.AIR;
         }
-        return translateToBedrock(session, bedrockItem, stack.getAmount(), stack.getNbt())
+        // Java item needs to be loaded separately. The mapping for tipped arrow would
+        return translateToBedrock(session, Registries.JAVA_ITEMS.get().get(stack.getId()), bedrockItem, stack.getAmount(), stack.getNbt())
                 .build();
     }
 
     @Nonnull
-    private static ItemData.Builder translateToBedrock(GeyserSession session, ItemMapping mapping, int count, CompoundTag tag) {
+    private static ItemData.Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, CompoundTag tag) {
         CompoundTag nbt = tag != null ? tag.clone() : null;
 
         // This is a fallback for maps with no nbt
-        if (nbt == null && mapping.getJavaIdentifier().equals("minecraft:filled_map")) {
+        if (nbt == null && javaItem == Items.FILLED_MAP) {
             nbt = new CompoundTag("");
             nbt.put(new IntTag("map", 0));
         }
 
         if (nbt != null) {
             for (NbtItemStackTranslator translator : NBT_TRANSLATORS) {
-                if (translator.acceptItem(mapping)) {
-                    translator.translateToBedrock(session, nbt, mapping);
+                if (translator.acceptItem(javaItem)) {
+                    translator.translateToBedrock(session, nbt, bedrockItem);
                 }
             }
         }
 
-        nbt = translateDisplayProperties(session, nbt, mapping);
+        nbt = translateDisplayProperties(session, nbt, bedrockItem);
         if (session.isAdvancedTooltips()) {
-            nbt = addAdvancedTooltips(nbt, mapping, session.locale());
+            nbt = addAdvancedTooltips(nbt, javaItem, session.locale());
         }
 
-        ItemStack itemStack = new ItemStack(mapping.getJavaId(), count, nbt);
+        ItemStack itemStack = new ItemStack(javaItem.javaId(), count, nbt);
 
-        ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(mapping.getJavaId(), DEFAULT_TRANSLATOR);
-        ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, mapping, session.getItemMappings());
-        if (mapping.isBlock()) {
-            builder.blockDefinition(mapping.getBedrockBlockDefinition());
+        ItemData.Builder builder = javaItem.translateToBedrock(itemStack, bedrockItem, session.getItemMappings());
+        if (bedrockItem.isBlock()) {
+            builder.blockDefinition(bedrockItem.getBedrockBlockDefinition());
         }
 
         if (nbt != null) {
@@ -220,7 +188,7 @@ public abstract class ItemTranslator {
         return builder;
     }
 
-    private static CompoundTag addAdvancedTooltips(CompoundTag nbt, ItemMapping mapping, String language) {
+    private static CompoundTag addAdvancedTooltips(CompoundTag nbt, Item item, String language) {
         CompoundTag newNbt = nbt;
         if (newNbt == null) {
             newNbt = new CompoundTag("nbt");
@@ -237,7 +205,7 @@ public abstract class ItemTranslator {
         if (listTag == null) {
             listTag = new ListTag("Lore");
         }
-        int maxDurability = mapping.getMaxDamage();
+        int maxDurability = item.maxDamage();
 
         if (maxDurability != 0) {
             Tag durabilityTag = newNbt.get("Damage");
@@ -256,7 +224,7 @@ public abstract class ItemTranslator {
             }
         }
 
-        listTag.add(new StringTag("", "§r§8" + mapping.getJavaIdentifier()));
+        listTag.add(new StringTag("", ChatColor.RESET + ChatColor.DARK_GRAY + item.javaIdentifier()));
         if (nbt != null) {
             Component component = Component.text()
                     .resetStyle()
@@ -283,9 +251,7 @@ public abstract class ItemTranslator {
             String[] canModifyBedrock = new String[canModifyJava.size()];
             for (int i = 0; i < canModifyBedrock.length; i++) {
                 // Get the Java identifier of the block that can be placed
-                String block = ((StringTag) canModifyJava.get(i)).getValue();
-                // Sometimes this is done but it's still valid
-                if (!block.startsWith("minecraft:")) block = "minecraft:" + block;
+                String block = Identifier.formalize(((StringTag) canModifyJava.get(i)).getValue());
                 // Get the Bedrock identifier of the item and replace it.
                 // This will unfortunately be limited - for example, beds and banners will be translated weirdly
                 canModifyBedrock[i] = BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.getOrDefault(block, block).replace("minecraft:", "");
@@ -304,9 +270,7 @@ public abstract class ItemTranslator {
             return ItemDefinition.AIR;
         }
 
-        int javaId = itemStack.getJavaId();
-        ItemMapping mapping = ITEM_STACK_TRANSLATORS.getOrDefault(javaId, DEFAULT_TRANSLATOR)
-                .getItemMapping(javaId, itemStack.getNbt(), session.getItemMappings());
+        ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getNbt(), session.getItemMappings());
 
         ItemDefinition definition = CustomItemTranslator.getCustomItem(itemStack.getNbt(), mapping);
         if (definition == null) {
@@ -317,50 +281,7 @@ public abstract class ItemTranslator {
         }
     }
 
-    private static final ItemTranslator DEFAULT_TRANSLATOR = new ItemTranslator() {
-        @Override
-        public List<ItemMapping> getAppliedItems() {
-            return null;
-        }
-    };
-
-    protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
-        if (itemStack == null) {
-            // Return, essentially, air
-            return ItemData.builder();
-        }
-        ItemData.Builder builder = ItemData.builder()
-                .definition(mapping.getBedrockDefinition())
-                .damage(mapping.getBedrockData())
-                .count(itemStack.getAmount());
-        if (itemStack.getNbt() != null) {
-            builder.tag(this.translateNbtToBedrock(itemStack.getNbt()));
-        }
-
-        CompoundTag nbt = itemStack.getNbt();
-        translateCustomItem(nbt, builder, mapping);
-
-        return builder;
-    }
-
-    public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
-        if (itemData == null) return null;
-        if (itemData.getTag() == null) {
-            return new ItemStack(mapping.getJavaId(), itemData.getCount(), new CompoundTag(""));
-        }
-        return new ItemStack(mapping.getJavaId(), itemData.getCount(), this.translateToJavaNBT("", itemData.getTag()));
-    }
-
-    /**
-     * Used for initialization only and only called once.
-     */
-    public abstract List<ItemMapping> getAppliedItems();
-
-    protected ItemMapping getItemMapping(int javaId, CompoundTag nbt, ItemMappings mappings) {
-        return mappings.getMapping(javaId);
-    }
-
-    protected NbtMap translateNbtToBedrock(CompoundTag tag) {
+    public static NbtMap translateNbtToBedrock(CompoundTag tag) {
         if (!tag.getValue().isEmpty()) {
             NbtMapBuilder builder = NbtMap.builder();
             for (Tag javaTag : tag.values()) {
@@ -375,7 +296,7 @@ public abstract class ItemTranslator {
         return NbtMap.EMPTY;
     }
 
-    private Object translateToBedrockNBT(Tag tag) {
+    private static Object translateToBedrockNBT(Tag tag) {
         if (tag instanceof CompoundTag compoundTag) {
             return translateNbtToBedrock(compoundTag);
         }
@@ -402,7 +323,7 @@ public abstract class ItemTranslator {
         return tag.getValue();
     }
 
-    private CompoundTag translateToJavaNBT(String name, NbtMap tag) {
+    public static CompoundTag translateToJavaNBT(String name, NbtMap tag) {
         CompoundTag javaTag = new CompoundTag(name);
         Map<String, Tag> javaValue = javaTag.getValue();
         if (tag != null && !tag.isEmpty()) {
@@ -419,7 +340,7 @@ public abstract class ItemTranslator {
         return javaTag;
     }
 
-    private Tag translateToJavaNBT(String name, Object object) {
+    private static Tag translateToJavaNBT(String name, Object object) {
         if (object instanceof int[]) {
             return new IntArrayTag(name, (int[]) object);
         }
@@ -529,7 +450,7 @@ public abstract class ItemTranslator {
 
             String translationKey = mapping.getTranslationString();
             // Reset formatting since Bedrock defaults to italics
-            display.put(new StringTag("Name", "§r§" + translationColor + MinecraftLocale.getLocaleString(translationKey, session.locale())));
+            display.put(new StringTag("Name", ChatColor.RESET + ChatColor.ESCAPE + translationColor + MinecraftLocale.getLocaleString(translationKey, session.locale())));
         }
 
         return tag;
@@ -538,7 +459,7 @@ public abstract class ItemTranslator {
     /**
      * Translates the custom model data of an item
      */
-    private static void translateCustomItem(CompoundTag nbt, ItemData.Builder builder, ItemMapping mapping) {
+    public static void translateCustomItem(CompoundTag nbt, ItemData.Builder builder, ItemMapping mapping) {
         ItemDefinition definition = CustomItemTranslator.getCustomItem(nbt, mapping);
         if (definition != null) {
             builder.definition(definition);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/NbtItemStackTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/NbtItemStackTranslator.java
index 5f22668df..a51e2307d 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/NbtItemStackTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/NbtItemStackTranslator.java
@@ -26,6 +26,7 @@
 package org.geysermc.geyser.translator.inventory.item;
 
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 
@@ -53,11 +54,11 @@ public abstract class NbtItemStackTranslator {
     /**
      * Gets whether this nbt translator takes in this item.
      *
-     * @param mapping Geyser's item mapping
+     * @param item Geyser's item mapping
      * @return if the item should be processed under this class
      */
-    public boolean acceptItem(ItemMapping mapping) {
+    public boolean acceptItem(Item item) {
         return true;
-    }
+    } // TODO
 
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/AxolotlBucketTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/AxolotlBucketTranslator.java
index 19809c12f..8f81f5b4e 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/AxolotlBucketTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/AxolotlBucketTranslator.java
@@ -28,6 +28,8 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
 import com.github.steveice10.opennbt.tag.builtin.ByteTag;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.StringTag;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.text.MinecraftLocale;
@@ -49,7 +51,7 @@ public class AxolotlBucketTranslator extends NbtItemStackTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return mapping.getJavaIdentifier().equals("minecraft:axolotl_bucket");
+    public boolean acceptItem(Item item) {
+        return item == Items.AXOLOTL_BUCKET;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BannerTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BannerTranslator.java
index 1bafabee8..2a88e4371 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BannerTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BannerTranslator.java
@@ -29,7 +29,7 @@ import com.github.steveice10.opennbt.tag.builtin.*;
 import org.cloudburstmc.nbt.NbtList;
 import org.cloudburstmc.nbt.NbtMap;
 import org.cloudburstmc.nbt.NbtType;
-import org.geysermc.geyser.network.GameProtocol;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
@@ -37,7 +37,10 @@ import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
 import org.geysermc.geyser.translator.inventory.item.NbtItemStackTranslator;
 
 import javax.annotation.Nonnull;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 @ItemRemapper
@@ -51,7 +54,7 @@ public class BannerTranslator extends NbtItemStackTranslator {
      */
     public static final ListTag OMINOUS_BANNER_PATTERN;
 
-    private final List<ItemMapping> appliedItems;
+    private final List<Item> appliedItems;
 
     static {
         OMINOUS_BANNER_PATTERN = new ListTag("Patterns");
@@ -76,8 +79,8 @@ public class BannerTranslator extends NbtItemStackTranslator {
     }
 
     public BannerTranslator() {
-        appliedItems = Arrays.stream(Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getItems())
-                .filter(entry -> entry.getJavaIdentifier().endsWith("banner"))
+        appliedItems = Registries.JAVA_ITEMS.get().stream()
+                .filter(entry -> entry.javaIdentifier().endsWith("banner"))
                 .collect(Collectors.toList());
     }
 
@@ -171,7 +174,7 @@ public class BannerTranslator extends NbtItemStackTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return appliedItems.contains(mapping);
+    public boolean acceptItem(Item item) {
+        return appliedItems.contains(item);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BasicItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BasicItemTranslator.java
index 5dcc76b49..da2a77979 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BasicItemTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BasicItemTranslator.java
@@ -44,7 +44,7 @@ public class BasicItemTranslator extends NbtItemStackTranslator {
         Tag damage = itemTag.get("Damage");
         if (damage instanceof IntTag) {
             int originalDurability = ((IntTag) damage).getValue();
-            int durability = ItemUtils.getCorrectBedrockDurability(session, mapping.getJavaId(), originalDurability);
+            int durability = ItemUtils.getCorrectBedrockDurability(mapping.getJavaItem(), originalDurability);
             if (durability != originalDurability) {
                 // Fix damage tag inconsistencies
                 itemTag.put(new IntTag("Damage", durability));
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/CrossbowTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/CrossbowTranslator.java
index c393c375f..40c0466b5 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/CrossbowTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/CrossbowTranslator.java
@@ -28,6 +28,8 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
 import com.github.steveice10.opennbt.tag.builtin.*;
 import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@@ -47,7 +49,7 @@ public class CrossbowTranslator extends NbtItemStackTranslator {
                 ItemMapping projectileMapping = session.getItemMappings().getMapping((String) projectile.get("id").getValue());
                 if (projectileMapping == null) return;
                 CompoundTag tag = projectile.get("tag");
-                ItemStack itemStack = new ItemStack(mapping.getJavaId(), (byte) projectile.get("Count").getValue(), tag);
+                ItemStack itemStack = new ItemStack(mapping.getJavaItem().javaId(), (byte) projectile.get("Count").getValue(), tag);
                 ItemData itemData = ItemTranslator.translateToBedrock(session, itemStack);
 
                 CompoundTag newProjectile = new CompoundTag("chargedItem");
@@ -78,7 +80,7 @@ public class CrossbowTranslator extends NbtItemStackTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return "minecraft:crossbow".equals(mapping.getJavaIdentifier());
+    public boolean acceptItem(Item item) {
+        return item == Items.CROSSBOW;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/EnchantedBookTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/EnchantedBookTranslator.java
index ad6c2e9f1..f42885077 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/EnchantedBookTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/EnchantedBookTranslator.java
@@ -28,6 +28,8 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.ListTag;
 import com.github.steveice10.opennbt.tag.builtin.Tag;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@@ -63,7 +65,7 @@ public class EnchantedBookTranslator extends NbtItemStackTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return "minecraft:enchanted_book".equals(mapping.getJavaIdentifier());
+    public boolean acceptItem(Item item) {
+        return item == Items.ENCHANTED_BOOK;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/FireworkRocketTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/FireworkRocketTranslator.java
index fdf898273..8b686f5ec 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/FireworkRocketTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/FireworkRocketTranslator.java
@@ -29,6 +29,8 @@ import com.github.steveice10.opennbt.tag.builtin.ByteTag;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.ListTag;
 import com.github.steveice10.opennbt.tag.builtin.Tag;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@@ -86,7 +88,7 @@ public class FireworkRocketTranslator extends FireworkBaseTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return "minecraft:firework_rocket".equals(mapping.getJavaIdentifier());
+    public boolean acceptItem(Item item) {
+        return item == Items.FIREWORK_ROCKET;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/FireworkStarTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/FireworkStarTranslator.java
index eca3272d1..23fb74fcc 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/FireworkStarTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/FireworkStarTranslator.java
@@ -29,6 +29,8 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.IntArrayTag;
 import com.github.steveice10.opennbt.tag.builtin.IntTag;
 import com.github.steveice10.opennbt.tag.builtin.Tag;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@@ -90,7 +92,7 @@ public class FireworkStarTranslator extends FireworkBaseTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return "minecraft:firework_star".equals(mapping.getJavaIdentifier());
+    public boolean acceptItem(Item item) {
+        return item == Items.FIREWORK_STAR;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/LeatherArmorTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/LeatherArmorTranslator.java
index 5e5920b4a..ea855ce52 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/LeatherArmorTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/LeatherArmorTranslator.java
@@ -27,6 +27,8 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
 
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.IntTag;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@@ -37,8 +39,8 @@ import java.util.List;
 @ItemRemapper
 public class LeatherArmorTranslator extends NbtItemStackTranslator {
 
-    private static final List<String> ITEMS = List.of("minecraft:leather_helmet", "minecraft:leather_chestplate",
-            "minecraft:leather_leggings", "minecraft:leather_boots", "minecraft:leather_horse_armor");
+    private static final List<Item> ITEMS = List.of(Items.LEATHER_HELMET, Items.LEATHER_CHESTPLATE,
+            Items.LEATHER_LEGGINGS, Items.LEATHER_BOOTS, Items.LEATHER_HORSE_ARMOR);
 
     @Override
     public void translateToBedrock(GeyserSession session, CompoundTag itemTag, ItemMapping mapping) {
@@ -67,7 +69,7 @@ public class LeatherArmorTranslator extends NbtItemStackTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return ITEMS.contains(mapping.getJavaIdentifier());
+    public boolean acceptItem(Item item) {
+        return ITEMS.contains(item);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/LodestoneCompassTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/LodestoneCompassTranslator.java
index 8025817f7..33a841f85 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/LodestoneCompassTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/LodestoneCompassTranslator.java
@@ -29,6 +29,8 @@ import com.github.steveice10.opennbt.tag.builtin.ByteTag;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.IntTag;
 import com.github.steveice10.opennbt.tag.builtin.Tag;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@@ -52,7 +54,7 @@ public class LodestoneCompassTranslator extends NbtItemStackTranslator {
     // Lodestone compasses cannot be touched in any of those places.
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return mapping.getJavaIdentifier().equals("minecraft:compass");
+    public boolean acceptItem(Item item) {
+        return item == Items.COMPASS;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/MapItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/MapItemTranslator.java
index 8fd44ef65..08b539167 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/MapItemTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/MapItemTranslator.java
@@ -26,6 +26,8 @@
 package org.geysermc.geyser.translator.inventory.item.nbt;
 
 import com.github.steveice10.opennbt.tag.builtin.*;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@@ -65,7 +67,7 @@ public class MapItemTranslator extends NbtItemStackTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return mapping.getJavaIdentifier().equals("minecraft:filled_map");
+    public boolean acceptItem(Item item) {
+        return item == Items.FILLED_MAP;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/PlayerHeadTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/PlayerHeadTranslator.java
index d4975f81a..f9256ba99 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/PlayerHeadTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/PlayerHeadTranslator.java
@@ -28,8 +28,11 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.StringTag;
 import com.github.steveice10.opennbt.tag.builtin.Tag;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.text.ChatColor;
 import org.geysermc.geyser.text.MinecraftLocale;
 import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
 import org.geysermc.geyser.translator.inventory.item.NbtItemStackTranslator;
@@ -56,7 +59,7 @@ public class PlayerHeadTranslator extends NbtItemStackTranslator {
                 }
                 // Add correct name of player skull
                 // TODO: It's always yellow, even with a custom name. Handle?
-                String displayName = "\u00a7r\u00a7e" + MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name.getValue());
+                String displayName = ChatColor.RESET + ChatColor.YELLOW + MinecraftLocale.getLocaleString("block.minecraft.player_head.named", session.locale()).replace("%s", name.getValue());
                 if (!itemTag.contains("display")) {
                     itemTag.put(new CompoundTag("display"));
                 }
@@ -66,7 +69,7 @@ public class PlayerHeadTranslator extends NbtItemStackTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return mapping.getJavaIdentifier().equals("minecraft:player_head");
+    public boolean acceptItem(Item item) {
+        return item == Items.PLAYER_HEAD;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/ShulkerBoxItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/ShulkerBoxItemTranslator.java
index f95c54e18..67fe3663a 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/ShulkerBoxItemTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/ShulkerBoxItemTranslator.java
@@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.inventory.item.nbt;
 
 import com.github.steveice10.mc.protocol.data.game.Identifier;
 import com.github.steveice10.opennbt.tag.builtin.*;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemRemapper;
@@ -80,7 +81,7 @@ public class ShulkerBoxItemTranslator extends NbtItemStackTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return mapping.getJavaIdentifier().contains("shulker_box");
+    public boolean acceptItem(Item item) {
+        return item.javaIdentifier().contains("shulker_box");
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/TropicalFishBucketTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/TropicalFishBucketTranslator.java
index 6313dc362..77fbdfebf 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/TropicalFishBucketTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/TropicalFishBucketTranslator.java
@@ -31,6 +31,8 @@ import net.kyori.adventure.text.format.NamedTextColor;
 import net.kyori.adventure.text.format.Style;
 import net.kyori.adventure.text.format.TextDecoration;
 import org.geysermc.geyser.entity.type.living.animal.TropicalFishEntity;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.text.MinecraftLocale;
@@ -90,7 +92,7 @@ public class TropicalFishBucketTranslator extends NbtItemStackTranslator {
     }
 
     @Override
-    public boolean acceptItem(ItemMapping mapping) {
-        return mapping.getJavaIdentifier().equals("minecraft:tropical_fish_bucket");
+    public boolean acceptItem(Item item) {
+        return item == Items.TROPICAL_FISH_BUCKET;
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
index 486d8906f..76c30a2a1 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
@@ -63,6 +63,8 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
 import org.geysermc.geyser.inventory.Inventory;
 import org.geysermc.geyser.inventory.PlayerInventory;
 import org.geysermc.geyser.inventory.click.Click;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.SpawnEggItem;
 import org.geysermc.geyser.level.block.BlockStateValues;
 import org.geysermc.geyser.registry.BlockRegistries;
 import org.geysermc.geyser.registry.type.ItemMapping;
@@ -259,7 +261,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
                         Block place checks end - client is good to go
                          */
 
-                        if (packet.getItemInHand() != null && session.getItemMappings().getSpawnEggs().contains(packet.getItemInHand().getDefinition())) {
+                        if (packet.getItemInHand() != null && session.getItemMappings().getMapping(packet.getItemInHand()).getJavaItem() instanceof SpawnEggItem) {
                             int blockState = session.getGeyser().getWorldManager().getBlockAt(session, packet.getBlockPosition());
                             if (blockState == BlockStateValues.JAVA_WATER_ID) {
                                 // Otherwise causes multiple mobs to spawn - just send a use item packet
@@ -321,7 +323,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
                         ItemMapping handItem = session.getPlayerInventory().getItemInHand().getMapping(session);
                         if (handItem.isBlock()) {
                             session.setLastBlockPlacePosition(blockPos);
-                            session.setLastBlockPlacedId(handItem.getJavaIdentifier());
+                            session.setLastBlockPlacedId(handItem.getJavaItem().javaIdentifier());
                         }
                         session.setInteracting(true);
                     }
@@ -332,7 +334,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
                         }
 
                         // Handled when sneaking
-                        if (session.getPlayerInventory().getItemInHand().getJavaId() == mappings.getStoredItems().shield().getJavaId()) {
+                        if (session.getPlayerInventory().getItemInHand().asItem() == Items.SHIELD) {
                             break;
                         }
 
@@ -342,7 +344,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
                                     packet.getItemInHand().getDefinition() != session.getItemMappings().getStoredItems().milkBucket().getBedrockDefinition()) {
                                 // Handled in case 0 if the item is not milk
                                 break;
-                            } else if (session.getItemMappings().getSpawnEggs().contains(packet.getItemInHand().getDefinition())) {
+                            } else if (session.getItemMappings().getMapping(packet.getItemInHand()).getJavaItem() instanceof SpawnEggItem) {
                                 // Handled in case 0
                                 break;
                             } else if (packet.getItemInHand().getDefinition() == session.getItemMappings().getStoredItems().glassBottle().getBedrockDefinition()) {
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java
index 6a3f3603c..d045a6c24 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMobEquipmentTranslator.java
@@ -31,6 +31,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.Server
 import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
 import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
@@ -61,7 +62,7 @@ public class BedrockMobEquipmentTranslator extends PacketTranslator<MobEquipment
 
         GeyserItemStack newItem = session.getPlayerInventory().getItemInHand();
 
-        if (session.isSneaking() && newItem.getJavaId() == session.getItemMappings().getStoredItems().shield().getJavaId()) {
+        if (session.isSneaking() && newItem.asItem() == Items.SHIELD) {
             // Activate shield since we are already sneaking
             // (No need to send a release item packet - Java doesn't do this when swapping items)
             // Required to do it a tick later or else it doesn't register
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java
index 756b63bc6..4cb5816a5 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java
@@ -37,6 +37,7 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
 import org.cloudburstmc.protocol.bedrock.packet.InteractPacket;
 import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
@@ -58,7 +59,7 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
 
         switch (packet.getAction()) {
             case INTERACT:
-                if (session.getPlayerInventory().getItemInHand().getJavaId() == session.getItemMappings().getStoredItems().shield().getJavaId()) {
+                if (session.getPlayerInventory().getItemInHand().asItem() == Items.SHIELD) {
                     break;
                 }
                 ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(entity.getEntityId(),
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java
index e284bbbea..126665f34 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java
@@ -241,7 +241,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
             case BOOL -> ENUM_BOOLEAN;
             case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc
             case BLOCK_STATE -> context.getBlockStates();
-            case ITEM_STACK -> context.session.getItemMappings().getItemNames();
+            case ITEM_STACK -> context.getItemNames();
             case COLOR -> VALID_COLORS;
             case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS;
             case RESOURCE -> handleResource(context, ((ResourceProperties) node.getProperties()).getRegistryKey(), false);
@@ -278,6 +278,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
         private Object biomesNoTags;
         private String[] blockStates;
         private String[] entityTypes;
+        private String[] itemNames;
 
         CommandBuilderContext(GeyserSession session) {
             this.session = session;
@@ -314,6 +315,13 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
             }
             return (entityTypes = Registries.JAVA_ENTITY_IDENTIFIERS.get().keySet().toArray(new String[0]));
         }
+
+        public String[] getItemNames() {
+            if (itemNames != null) {
+                return itemNames;
+            }
+            return (itemNames = Registries.JAVA_ITEM_IDENTIFIERS.get().keySet().toArray(new String[0]));
+        }
     }
 
     @Getter
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java
index 93a840da6..a1377a796 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java
@@ -168,8 +168,8 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
             // Sort the list by each output item's Java identifier - this is how it's sorted on Java, and therefore
             // We can get the correct order for button pressing
             data.getValue().sort(Comparator.comparing((stoneCuttingRecipeData ->
-                    session.getItemMappings().getMapping(stoneCuttingRecipeData.getResult())
-                            .getJavaIdentifier())));
+                    Registries.JAVA_ITEMS.get().get(stoneCuttingRecipeData.getResult().getId())
+                            .javaIdentifier())));
 
             // Now that it's sorted, let's translate these recipes
             int buttonId = 0;
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java
index 5ff82771a..9e4f30f14 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java
@@ -33,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
 import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.entity.type.LivingEntity;
 import org.geysermc.geyser.entity.type.player.PlayerEntity;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.skin.FakeHeadProvider;
 import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
@@ -64,7 +65,7 @@ public class JavaSetEquipmentTranslator extends PacketTranslator<ClientboundSetE
                     ItemStack javaItem = equipment.getItem();
                     if (livingEntity instanceof PlayerEntity
                             && javaItem != null
-                            && javaItem.getId() == session.getItemMappings().getStoredItems().playerHead().getJavaId()
+                            && javaItem.getId() == Items.PLAYER_HEAD.javaId()
                             && javaItem.getNbt() != null
                             && javaItem.getNbt().get("SkullOwner") instanceof CompoundTag profile) {
                         FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, profile);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java
index 26c1a9069..d4cb46a1c 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaMerchantOffersTranslator.java
@@ -38,6 +38,7 @@ import org.cloudburstmc.protocol.bedrock.packet.UpdateTradePacket;
 import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.inventory.Inventory;
 import org.geysermc.geyser.inventory.MerchantContainer;
+import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
@@ -163,7 +164,7 @@ public class JavaMerchantOffersTranslator extends PacketTranslator<ClientboundMe
 
         // Bedrock expects all price adjustments to be applied to the item's count
         int count = stack.getAmount() + ((int) Math.max(Math.floor(stack.getAmount() * demand * priceMultiplier), 0)) + specialPrice;
-        count = MathUtils.constrain(count, 1, mapping.getStackSize());
+        count = MathUtils.constrain(count, 1, Registries.JAVA_ITEMS.get().get(stack.getId()).maxStackSize());
 
         return getItemTag(session, stack, mapping, count);
     }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java
index 5da57bfeb..4249be6fc 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java
@@ -27,7 +27,9 @@ package org.geysermc.geyser.translator.protocol.java.level;
 
 import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCooldownPacket;
 import org.cloudburstmc.protocol.bedrock.packet.PlayerStartItemCooldownPacket;
-import org.geysermc.geyser.inventory.item.StoredItemMappings;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
+import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
@@ -37,15 +39,13 @@ public class JavaCooldownTranslator extends PacketTranslator<ClientboundCooldown
 
     @Override
     public void translate(GeyserSession session, ClientboundCooldownPacket packet) {
-        StoredItemMappings itemMappings = session.getItemMappings().getStoredItems();
-
-        int itemId = packet.getItemId();
+        Item item = Registries.JAVA_ITEMS.get().get(packet.getItemId());
         // Not every item, as of 1.19, appears to be server-driven. Just these two.
         // Use a map here if it gets too big.
         String cooldownCategory;
-        if (itemId == itemMappings.goatHorn().getJavaId()) {
+        if (item == Items.GOAT_HORN) {
             cooldownCategory = "goat_horn";
-        } else if (itemId == itemMappings.shield().getJavaId()) {
+        } else if (item == Items.SHIELD) {
             cooldownCategory = "shield";
         } else {
             cooldownCategory = null;
diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java
index fd37357ef..ef6be0e9d 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/sound/BlockSoundInteractionTranslator.java
@@ -75,7 +75,7 @@ public interface BlockSoundInteractionTranslator extends SoundInteractionTransla
                     continue;
                 }
                 if (handIdentifier == null) {
-                    handIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
+                    handIdentifier = itemInHand.asItem().javaIdentifier();
                 }
                 boolean contains = false;
                 for (String itemIdentifier : interactionEntry.getKey().items()) {
diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/block/BucketSoundInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/block/BucketSoundInteractionTranslator.java
index dc3098d8e..7a5e86af7 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/sound/block/BucketSoundInteractionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/sound/block/BucketSoundInteractionTranslator.java
@@ -42,7 +42,7 @@ public class BucketSoundInteractionTranslator implements BlockSoundInteractionTr
             return; // No bucket was really interacted with
         }
         GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand();
-        String handItemIdentifier = itemStack.getMapping(session).getJavaIdentifier();
+        String handItemIdentifier = itemStack.asItem().javaIdentifier();
         if (!BlockSoundInteractionTranslator.canInteract(session, itemStack, identifier)) {
             return;
         }
diff --git a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
index 09fc8f385..88a100955 100644
--- a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
@@ -37,6 +37,7 @@ import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.entity.type.living.ArmorStandEntity;
 import org.geysermc.geyser.entity.type.living.animal.AnimalEntity;
 import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.Locale;
@@ -217,14 +218,14 @@ public final class EntityUtils {
      * Determine if an action would result in a successful bucketing of the given entity.
      */
     public static boolean attemptToBucket(GeyserSession session, GeyserItemStack itemInHand) {
-        return itemInHand.getJavaId() == session.getItemMappings().getStoredItems().waterBucket().getJavaId();
+        return itemInHand.asItem() == Items.WATER_BUCKET;
     }
 
     /**
      * Attempt to determine the result of saddling the given entity.
      */
-    public static InteractionResult attemptToSaddle(GeyserSession session, Entity entityToSaddle, GeyserItemStack itemInHand) {
-        if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().saddle().getJavaId()) {
+    public static InteractionResult attemptToSaddle(Entity entityToSaddle, GeyserItemStack itemInHand) {
+        if (itemInHand.asItem() == Items.SADDLE) {
             if (!entityToSaddle.getFlag(EntityFlag.SADDLED) && !entityToSaddle.getFlag(EntityFlag.BABY)) {
                 // Saddle
                 return InteractionResult.SUCCESS;
diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java
index 505b0828d..0141e22ea 100644
--- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java
@@ -49,6 +49,7 @@ import org.geysermc.geyser.inventory.click.Click;
 import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
 import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
 import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.level.BedrockDimension;
 import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.registry.type.ItemMapping;
@@ -178,7 +179,7 @@ public class InventoryUtils {
      * Checks to see if an item stack represents air or has no count.
      */
     public static boolean isEmpty(@Nullable ItemStack itemStack) {
-        return itemStack == null || itemStack.getId() == ItemMapping.AIR.getJavaId() || itemStack.getAmount() <= 0;
+        return itemStack == null || itemStack.getId() == Items.AIR.javaId() || itemStack.getAmount() <= 0;
     }
 
     /**
@@ -294,7 +295,7 @@ public class InventoryUtils {
                 continue;
             }
             // If this isn't the item we're looking for
-            if (!geyserItem.getMapping(session).getJavaIdentifier().equals(itemName)) {
+            if (!geyserItem.asItem().javaIdentifier().equals(itemName)) {
                 continue;
             }
 
@@ -310,7 +311,7 @@ public class InventoryUtils {
                 continue;
             }
             // If this isn't the item we're looking for
-            if (!geyserItem.getMapping(session).getJavaIdentifier().equals(itemName)) {
+            if (!geyserItem.asItem().javaIdentifier().equals(itemName)) {
                 continue;
             }
 
@@ -323,10 +324,10 @@ public class InventoryUtils {
         if (session.getGameMode() == GameMode.CREATIVE) {
             int slot = findEmptyHotbarSlot(inventory);
 
-            ItemMapping mapping = session.getItemMappings().getMapping(itemName);
+            ItemMapping mapping = session.getItemMappings().getMapping(itemName); // TODO
             if (mapping != null) {
                 ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket(slot,
-                        new ItemStack(mapping.getJavaId()));
+                        new ItemStack(mapping.getJavaItem().javaId()));
                 if ((slot - 36) != inventory.getHeldItemSlot()) {
                     setHotbarItem(session, slot);
                 }
diff --git a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java
index 92967a10b..d44d16024 100644
--- a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java
@@ -29,13 +29,12 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.ListTag;
 import com.github.steveice10.opennbt.tag.builtin.StringTag;
 import com.github.steveice10.opennbt.tag.builtin.Tag;
-import it.unimi.dsi.fastutil.ints.Int2IntMap;
-import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.Item;
 
 import javax.annotation.Nullable;
 
 public class ItemUtils {
-    private static Int2IntMap DYE_COLORS = null;
 
     public static int getEnchantmentLevel(@Nullable CompoundTag itemNBTData, String enchantmentId) {
         if (itemNBTData == null) {
@@ -60,8 +59,8 @@ public class ItemUtils {
     /**
      * @return the correct Bedrock durability for this item.
      */
-    public static int getCorrectBedrockDurability(GeyserSession session, int javaId, int original) {
-        if (javaId == session.getItemMappings().getStoredItems().fishingRod().getJavaId()) {
+    public static int getCorrectBedrockDurability(Item item, int original) {
+        if (item == Items.FISHING_ROD) {
             // Java durability: 64
             // Bedrock durability : 384
             // 384 / 64 = 6
@@ -84,19 +83,4 @@ public class ItemUtils {
         }
         return null;
     }
-
-    /**
-     * Return the dye color associated with this Java item ID, if any. Returns -1 if no dye color exists for this item.
-     */
-    public static int dyeColorFor(int javaId) {
-        return DYE_COLORS.get(javaId);
-    }
-
-    public static void setDyeColors(Int2IntMap dyeColors) {
-        if (DYE_COLORS != null) {
-            throw new RuntimeException();
-        }
-        dyeColors.defaultReturnValue(-1);
-        DYE_COLORS = dyeColors;
-    }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java b/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java
index 58e0b131a..aa174497b 100644
--- a/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java
@@ -29,8 +29,9 @@ import com.github.steveice10.mc.protocol.data.game.statistic.*;
 import it.unimi.dsi.fastutil.objects.Object2IntMap;
 import org.geysermc.cumulus.form.SimpleForm;
 import org.geysermc.cumulus.util.FormImage;
+import org.geysermc.geyser.item.type.Item;
 import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.ItemMappings;
+import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.text.GeyserLocale;
 import org.geysermc.geyser.text.MinecraftLocale;
@@ -74,7 +75,7 @@ public class StatisticsUtils {
 
                             List<String> content = new ArrayList<>();
 
-                            ItemMappings mappings = session.getItemMappings();
+                            List<Item> itemRegistry = Registries.JAVA_ITEMS.get();
                             switch (response.clickedButtonId()) {
                                 case 0:
                                     builder.title("stat.generalButton");
@@ -105,7 +106,7 @@ public class StatisticsUtils {
 
                                     for (Object2IntMap.Entry<Statistic> entry : session.getStatistics().object2IntEntrySet()) {
                                         if (entry.getKey() instanceof BreakItemStatistic statistic) {
-                                            String item = mappings.getMapping(statistic.getId()).getJavaIdentifier();
+                                            String item = itemRegistry.get(statistic.getId()).javaIdentifier();
                                             content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue());
                                         }
                                     }
@@ -115,7 +116,7 @@ public class StatisticsUtils {
 
                                     for (Object2IntMap.Entry<Statistic> entry : session.getStatistics().object2IntEntrySet()) {
                                         if (entry.getKey() instanceof CraftItemStatistic statistic) {
-                                            String item = mappings.getMapping(statistic.getId()).getJavaIdentifier();
+                                            String item = itemRegistry.get(statistic.getId()).javaIdentifier();
                                             content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue());
                                         }
                                     }
@@ -125,7 +126,7 @@ public class StatisticsUtils {
 
                                     for (Object2IntMap.Entry<Statistic> entry : session.getStatistics().object2IntEntrySet()) {
                                         if (entry.getKey() instanceof UseItemStatistic statistic) {
-                                            String item = mappings.getMapping(statistic.getId()).getJavaIdentifier();
+                                            String item = itemRegistry.get(statistic.getId()).javaIdentifier();
                                             content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue());
                                         }
                                     }
@@ -135,7 +136,7 @@ public class StatisticsUtils {
 
                                     for (Object2IntMap.Entry<Statistic> entry : session.getStatistics().object2IntEntrySet()) {
                                         if (entry.getKey() instanceof PickupItemStatistic statistic) {
-                                            String item = mappings.getMapping(statistic.getId()).getJavaIdentifier();
+                                            String item = itemRegistry.get(statistic.getId()).javaIdentifier();
                                             content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue());
                                         }
                                     }
@@ -145,7 +146,7 @@ public class StatisticsUtils {
 
                                     for (Object2IntMap.Entry<Statistic> entry : session.getStatistics().object2IntEntrySet()) {
                                         if (entry.getKey() instanceof DropItemStatistic statistic) {
-                                            String item = mappings.getMapping(statistic.getId()).getJavaIdentifier();
+                                            String item = itemRegistry.get(statistic.getId()).javaIdentifier();
                                             content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue());
                                         }
                                     }
diff --git a/core/src/test/java/org/geysermc/geyser/translator/inventory/item/CustomItemsTest.java b/core/src/test/java/org/geysermc/geyser/translator/inventory/item/CustomItemsTest.java
index 7af330ef7..5b1781e7b 100644
--- a/core/src/test/java/org/geysermc/geyser/translator/inventory/item/CustomItemsTest.java
+++ b/core/src/test/java/org/geysermc/geyser/translator/inventory/item/CustomItemsTest.java
@@ -29,10 +29,12 @@ import com.github.steveice10.opennbt.tag.builtin.ByteTag;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
 import com.github.steveice10.opennbt.tag.builtin.IntTag;
 import it.unimi.dsi.fastutil.Pair;
+import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
 import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
 import org.geysermc.geyser.api.item.custom.CustomItemOptions;
 import org.geysermc.geyser.api.util.TriState;
 import org.geysermc.geyser.item.GeyserCustomItemOptions;
+import org.geysermc.geyser.item.Items;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.junit.Assert;
 import org.junit.Before;
@@ -59,7 +61,7 @@ public class CustomItemsTest {
         CustomItemOptions f = new GeyserCustomItemOptions(TriState.FALSE, OptionalInt.of(8), OptionalInt.of(6));
         CustomItemOptions g = new GeyserCustomItemOptions(TriState.NOT_SET, OptionalInt.of(20), OptionalInt.empty());
 
-        Map<CustomItemOptions, ItemDefinition> optionsToId = new HashMap<>();
+        Map<CustomItemOptions, ItemDefinition> optionsToId = new Object2ObjectArrayMap<>();
         // Order here is important, hence why we're using an array map
         optionsToId.put(g, new ItemDefinition("geyser:test_item_7", 7, true));
         optionsToId.put(f, new ItemDefinition("geyser:test_item_6", 6, true));
@@ -113,7 +115,7 @@ public class CustomItemsTest {
 
         testMappingWithDamage = ItemMapping.builder()
                 .customItemOptions(customItemOptions)
-                .maxDamage(100)
+                .javaItem(Items.WOODEN_PICKAXE)
                 .build();
 
         // Test differences with items with no max damage
@@ -127,7 +129,7 @@ public class CustomItemsTest {
 
         testMappingWithNoDamage = ItemMapping.builder()
                 .customItemOptions(customItemOptions)
-                .maxDamage(0)
+                .javaItem(Items.BEDROCK)
                 .build();
     }