diff --git a/game/client/build.gradle.kts b/game/client/build.gradle.kts
index 75d30edb7..faee365fa 100644
--- a/game/client/build.gradle.kts
+++ b/game/client/build.gradle.kts
@@ -48,9 +48,11 @@ dependencies {
     implementation(libs.gson)?.let { include(it) }
     implementation(libs.brigadier)?.let { include(it) }
     implementation(libs.bundles.log4j)?.let { include(it) }
+    implementation(project(":util:nbt"))?.let { include(it) }
+    implementation(project(":util:logging"))?.let { include(it) }
     // </core dependencies>
 
-    implementation("legacy-lwjgl3:legacy-lwjgl3:1.0.1")?.let { include(it) }
+    implementation("legacy-lwjgl3:legacy-lwjgl3:1.0.3")?.let { include(it) }
 
     implementation(libs.bundles.lwjgl)
     for (lib in libs.bundles.lwjgl.get()) {
diff --git a/game/client/src/main/java/net/betterthanadventure/utils/ResetBiomes.java b/game/client/src/main/java/net/betterthanadventure/utils/ResetBiomes.java
index 8be877107..6e68623f5 100644
--- a/game/client/src/main/java/net/betterthanadventure/utils/ResetBiomes.java
+++ b/game/client/src/main/java/net/betterthanadventure/utils/ResetBiomes.java
@@ -8,9 +8,9 @@ import java.util.List;
 import java.util.Map;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
-import com.mojang.nbt.Tag;
+import com.mojang.nbt.tags.Tag;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.core.world.ProgressListener;
diff --git a/game/client/src/main/java/net/minecraft/client/Minecraft.java b/game/client/src/main/java/net/minecraft/client/Minecraft.java
index ff7e67aad..1a2d32c65 100644
--- a/game/client/src/main/java/net/minecraft/client/Minecraft.java
+++ b/game/client/src/main/java/net/minecraft/client/Minecraft.java
@@ -13,7 +13,7 @@ import java.net.URL;
 import java.util.*;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.client.entity.ClientSkinVariantList;
 import net.minecraft.client.entity.player.PlayerLocal;
 import net.minecraft.client.gui.*;
diff --git a/game/client/src/main/java/net/minecraft/client/entity/particle/Particle.java b/game/client/src/main/java/net/minecraft/client/entity/particle/Particle.java
index 4b9a0c36f..1264405f7 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/particle/Particle.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/particle/Particle.java
@@ -6,7 +6,7 @@ import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 
 /**
diff --git a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java
index 06ef3e025..01899d60b 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java
@@ -2,7 +2,7 @@ package net.minecraft.client.entity.player;
 
 import com.mojang.brigadier.exceptions.CommandSyntaxException;
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.particle.ParticlePickupAnimation;
diff --git a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerRemote.java b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerRemote.java
index 05400c3d4..73a8e8ae9 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerRemote.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerRemote.java
@@ -4,7 +4,7 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.util.helper.DamageType;
 import net.minecraft.core.util.helper.GetSkinUrlThread;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/TooltipElement.java b/game/client/src/main/java/net/minecraft/client/gui/TooltipElement.java
index bc12a1438..ff44062bb 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/TooltipElement.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/TooltipElement.java
@@ -16,7 +16,7 @@ import net.minecraft.client.gui.guidebook.SlotGuidebook;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.opengl.GL11;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 public class TooltipElement extends Gui
 {
diff --git a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
index 84e6d65ad..ddcf6c90a 100644
--- a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
+++ b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
@@ -881,7 +881,7 @@ public class RenderGlobal
 
         // Render sun
         float size = 30F;
-        textureManager.loadTexture("/terrain/sun.png").bind();
+        textureManager.loadTexture("/assets/minecraft/textures/terrain/sun.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, sunAlpha);
         t.startDrawingQuads();
         t.addVertexWithUV(-size, 100D, -size, 0.0D, 0.0D);
@@ -938,7 +938,7 @@ public class RenderGlobal
             rainbowBrightness += rainbowBrightnessDelta * partialTick;
 
             // Draws and colors ring textures to make the rainbow
-            textureManager.loadTexture("/terrain/rainbow.png").bind();
+            textureManager.loadTexture("/assets/minecraft/textures/terrain/rainbow.png").bind();
             t.startDrawingQuads();
             final int iterations = 10;
             for (int i = 0; i < iterations; i++) {
@@ -963,7 +963,7 @@ public class RenderGlobal
 
         // Render moon
         size = 20F;
-        textureManager.loadTexture("/terrain/moon.png").bind();
+        textureManager.loadTexture("/assets/minecraft/textures/terrain/moon.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, sunAlpha);
         t.startDrawingQuads();
         t.addVertexWithUV(-size, -100D, size, 1.0D, 1.0D);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java
index 254d2dc36..d4caf3503 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java
@@ -2,6 +2,7 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.LightmapHelper;
+import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
@@ -10,6 +11,7 @@ import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import org.jetbrains.annotations.Nullable;
+import org.lwjgl.opengl.GL11;
 
 public class BlockModelPumice<T extends BlockLogic> extends BlockModelStandard<T> {
     private boolean lavaFlag = false;
@@ -34,10 +36,24 @@ public class BlockModelPumice<T extends BlockLogic> extends BlockModelStandard<T
 
     @Override
     public void renderBlockOnInventory(Tessellator tessellator, int metadata, float brightness, float alpha, @Nullable Integer lightmapCoordinate) {
+        if(renderBlocks.useInventoryTint) {
+            int color = BlockColorDispatcher.getInstance().getDispatch(block).getFallbackColor(metadata);
+            float r = (float) (color >> 16 & 0xff) / 255F;
+            float g = (float) (color >> 8 & 0xff) / 255F;
+            float b = (float) (color & 0xff) / 255F;
+            GL11.glColor4f(r * brightness, g * brightness, b * brightness, alpha);
+        }else {
+            GL11.glColor4f(brightness, brightness, brightness, alpha);
+        }
+        float yOffset = 0.5F;
+
+        GL11.glTranslatef(-0.5F, 0.0F - yOffset, -0.5F);
+
         lavaFlag = true;
         boolean ob = renderBlocks.overbright;
         renderBlocks.overbright = true;
-        AABB bounds = AABB.getTemporaryBB(0.005, 0.005, 0.005, 0.995, 0.995, 0.995);
+        final double depthFixOffset = 0.001d;
+        AABB bounds = AABB.getTemporaryBB(depthFixOffset, depthFixOffset, depthFixOffset, 1 - depthFixOffset, 1 - depthFixOffset, 1 - depthFixOffset);
         renderBlockWithBounds(tessellator, bounds, metadata, brightness, alpha, LightmapHelper.getLightmapCoord(15, 15));
 
         renderBlocks.overbright = ob;
@@ -47,6 +63,8 @@ public class BlockModelPumice<T extends BlockLogic> extends BlockModelStandard<T
         }
         bounds.set(0, 0, 0, 1, 1, 1);
         renderBlockWithBounds(tessellator, bounds, metadata, brightness, alpha, lightmapCoordinate);
+
+        GL11.glTranslatef(0.5F, yOffset, 0.5F);
     }
 
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRenderer.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRenderer.java
index fc54fdee1..fe24d1e57 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRenderer.java
@@ -94,10 +94,10 @@ public class MobRenderer<T extends Mob> extends EntityRenderer<T>
             }
 
             renderAdditional(entity, partialTick);
-            float f9 = entity.getBrightness(partialTick);
-            if (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) f9 = 1.0f;
-            int j = getOverlayColor(entity, f9, partialTick);
-            if((j >> 24 & 0xff) > 0 || entity.hurtTime > 0 || entity.deathTime > 0)
+            float brightness = entity.getBrightness(partialTick);
+            if (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) brightness = 1.0f;
+            int argb = getOverlayColor(entity, brightness, partialTick);
+            if((argb >> 24 & 0xff) > 0 || entity.hurtTime > 0 || entity.deathTime > 0)
             {
                 GL11.glDisable(GL11.GL_TEXTURE_2D);
                 GL11.glDisable(GL11.GL_ALPHA_TEST);
@@ -106,33 +106,33 @@ public class MobRenderer<T extends Mob> extends EntityRenderer<T>
                 GL11.glDepthFunc(514);
                 if(entity.hurtTime > 0 || entity.deathTime > 0)
                 {
-                    GL11.glColor4f(f9, 0.0F, 0.0F, 0.4F);
+                    GL11.glColor4f(brightness, 0.0F, 0.0F, 0.4F);
                     mainModel.render(walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale);
                     if (overlayModel != null) overlayModel.render(walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale);
                     for(int k = 0; k < MAX_ARMOR_LAYERS; k++)
                     {
                         if(prepareArmor(entity, k, partialTick))
                         {
-                            GL11.glColor4f(f9, 0.0F, 0.0F, 0.4F);
+                            GL11.glColor4f(brightness, 0.0F, 0.0F, 0.4F);
                             armorModel.render(walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale);
                         }
                     }
 
                 }
-                if((j >> 24 & 0xff) > 0)
+                if((argb >> 24 & 0xff) > 0)
                 {
-                    float f10 = (float)(j >> 16 & 0xff) / 255F;
-                    float f11 = (float)(j >> 8 & 0xff) / 255F;
-                    float f12 = (float)(j & 0xff) / 255F;
-                    float f13 = (float)(j >> 24 & 0xff) / 255F;
-                    GL11.glColor4f(f10, f11, f12, f13);
+                    float r = (float)(argb >> 16 & 0xff) / 255F;
+                    float g = (float)(argb >> 8 & 0xff) / 255F;
+                    float b = (float)(argb & 0xff) / 255F;
+                    float a = (float)(argb >> 24 & 0xff) / 255F;
+                    GL11.glColor4f(r, g, b, a);
                     mainModel.render(walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale);
                     if (overlayModel != null) overlayModel.render(walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale);
                     for(int l = 0; l < MAX_ARMOR_LAYERS; l++)
                     {
                         if(prepareArmor(entity, l, partialTick))
                         {
-                            GL11.glColor4f(f10, f11, f12, f13);
+                            GL11.glColor4f(r, g, b, a);
                             armorModel.render(walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale);
                         }
                     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGhast.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGhast.java
index 353906b40..93335d9d6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGhast.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGhast.java
@@ -32,6 +32,5 @@ public class MobRendererGhast extends MobRenderer<MobGhast>
         float f2 = (8F + charge) / 2.0F;
         float f3 = (8F + 1.0F / charge) / 2.0F;
         GL11.glScalef(f3, f2, f3);
-        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java
index 097660555..da22957f8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java
@@ -6,6 +6,7 @@ import net.minecraft.client.entity.player.PlayerLocal;
 import net.minecraft.client.render.BlockEntityRenderDispatcher;
 import net.minecraft.client.render.Font;
 import net.minecraft.client.render.Lighting;
+import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.PlayerSkinParser;
 import net.minecraft.client.render.RenderBlocks;
 import net.minecraft.client.render.block.model.BlockModel;
@@ -18,6 +19,7 @@ import net.minecraft.client.render.model.ModelPlayer;
 import net.minecraft.client.render.model.ModelPlayerSlim;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
+import net.minecraft.core.Global;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.motion.CarriedBlock;
@@ -87,7 +89,8 @@ public class MobRendererPlayer extends MobRenderer<Player>
     	
     	if(renderCape) {
             GL11.glPushMatrix();
-            GL11.glColor4f(1f, 1f, 1f, 1f);
+            float brightness = (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) ? 1 : player.getBrightness(partialTick);
+            GL11.glColor4f(brightness, brightness, brightness, 1f);
             GL11.glTranslatef(0.0F, 0.0F, 0.125F);
             float yawOff = player.yBodyRotO + (player.yBodyRot - player.yBodyRotO) * partialTick;
             float bodyAngle = 5;
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelBiped.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelBiped.java
index eafc96b12..ac7602a22 100644
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelBiped.java
+++ b/game/client/src/main/java/net/minecraft/client/render/model/ModelBiped.java
@@ -142,7 +142,11 @@ public class ModelBiped extends ModelBase
             legRight.xRot -= 0.0F;
             legLeft.xRot -= 0.0F;
             armRight.xRot += 0.4F;
-            armLeft.xRot += 0.4F;
+//            armLeft.xRot += 0.4F;
+            if (holdingLarge) {
+                armRight.xRot -= 0.4f;
+                armLeft.xRot -= 0.5f;
+            }
             legRight.z = 4F;
             legLeft.z = 4F;
             legRight.y = 9F;
diff --git a/game/client/src/main/java/net/minecraft/client/world/save/SaveHandlerClientMP.java b/game/client/src/main/java/net/minecraft/client/world/save/SaveHandlerClientMP.java
index 38a3d9e87..ad4411534 100644
--- a/game/client/src/main/java/net/minecraft/client/world/save/SaveHandlerClientMP.java
+++ b/game/client/src/main/java/net/minecraft/client/world/save/SaveHandlerClientMP.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.world.save;
 
 import net.minecraft.core.entity.player.Player;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.chunk.IChunkLoader;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.save.DimensionData;
diff --git a/game/client/src/main/resources/assets/minecraft/textures/terrain/moon.png b/game/client/src/main/resources/assets/minecraft/textures/terrain/moon.png
new file mode 100644
index 000000000..61cebbc7e
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/terrain/moon.png differ
diff --git a/game/client/src/main/resources/terrain/rainbow.png b/game/client/src/main/resources/assets/minecraft/textures/terrain/rainbow.png
similarity index 100%
rename from game/client/src/main/resources/terrain/rainbow.png
rename to game/client/src/main/resources/assets/minecraft/textures/terrain/rainbow.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/terrain/sun.png b/game/client/src/main/resources/assets/minecraft/textures/terrain/sun.png
new file mode 100644
index 000000000..d3433441f
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/terrain/sun.png differ
diff --git a/game/core/build.gradle.kts b/game/core/build.gradle.kts
index a206ea0dc..3b8b424c3 100644
--- a/game/core/build.gradle.kts
+++ b/game/core/build.gradle.kts
@@ -34,7 +34,10 @@ dependencies {
     implementation(libs.gson)
     implementation(libs.brigadier)
     implementation(libs.bundles.log4j)
+    implementation(project(":util:nbt"))
+    implementation(project(":util:logging"))
     // </core dependencies>
+
 }
 
 java {
diff --git a/game/core/src/main/java/com/mojang/nbt/CorruptedNBTException.java b/game/core/src/main/java/com/mojang/nbt/CorruptedNBTException.java
deleted file mode 100644
index 7d15d5f34..000000000
--- a/game/core/src/main/java/com/mojang/nbt/CorruptedNBTException.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.mojang.nbt;
-
-import java.io.IOException;
-
-public class CorruptedNBTException extends IOException {
-    public CorruptedNBTException() {
-        super();
-    }
-
-    public CorruptedNBTException(String message) {
-        super(message);
-    }
-}
diff --git a/game/core/src/main/java/com/mojang/nbt/LongArrayTag.java b/game/core/src/main/java/com/mojang/nbt/LongArrayTag.java
deleted file mode 100644
index 8042bdea3..000000000
--- a/game/core/src/main/java/com/mojang/nbt/LongArrayTag.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.mojang.nbt;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-public class LongArrayTag extends Tag<long[]>{
-    public LongArrayTag()
-    {
-        setValue(new long[0]);
-    }
-
-    public LongArrayTag(long[] array)
-    {
-        super(array);
-    }
-    @Override
-    void write(DataOutput dos)
-        throws IOException
-    {
-        dos.writeInt(getValue().length);
-        byte[] bytes = new byte[getValue().length * 4];
-        ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(getValue());
-        dos.write(bytes);
-
-    }
-
-    @Override
-    void read(DataInput dis)
-        throws IOException
-    {
-        int length = dis.readInt();
-        setValue(new long[length]);
-        byte[] bytes = new byte[length * 4];
-        dis.readFully(bytes);
-        ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().get(getValue());
-    }
-
-    @Override
-    public byte getId() {
-        return 13;
-    }
-}
diff --git a/game/core/src/main/java/com/mojang/nbt/Tag.java b/game/core/src/main/java/com/mojang/nbt/Tag.java
deleted file mode 100644
index 93a358bc4..000000000
--- a/game/core/src/main/java/com/mojang/nbt/Tag.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package com.mojang.nbt;
-
-import java.io.*;
-import java.util.Objects;
-
-public abstract class Tag<T>
-{
-    /**
-     * The key of the tag.
-     */
-    private String name = null;
-    /**
-     * The value of the tag.
-     */
-    private T value;
-
-    public Tag() { }
-
-    public Tag(T value)
-    {
-        this.value = value;
-    }
-
-    /**
-     * Reads the contents of the tag from the input stream.
-     * @param dis The stream to read the tag data from.
-     * @throws IOException Thrown if reading from the stream failed.
-     */
-    abstract void read(DataInput dis)
-        throws IOException;
-
-    /**
-     * Writes the contents of the tag to the output stream.
-     * @param dos The stream to write the tag data to.
-     * @throws IOException Thrown if writing to the stream failed.
-     */
-    abstract void write(DataOutput dos)
-        throws IOException;
-
-    /**
-     * Fetches the ID of the tag's type.
-     * @return The ID of the tag's type.
-     */
-    public abstract byte getId();
-
-    /**
-     * Fetches the tag's name.
-     * @return The tag's name.
-     */
-    public String getTagName()
-    {
-        if (name == null)
-        {
-            return "";
-        }
-        else
-        {
-            return name;
-        }
-    }
-
-    /**
-     * Sets the tag's key.
-     * @param key The new key of the tag.
-     * @return The tag that had its key set.
-     */
-    public Tag<T> setName(String key)
-    {
-        this.name = key;
-        return this;
-    }
-
-    /**
-     * Fetches the tag's value.
-     * @return The tag's value.
-     */
-    public T getValue()
-    {
-        return value;
-    }
-
-    /**
-     * Sets the tag's value.
-     * @param value The new value of the tag.
-     * @return The tag that had its value set.
-     */
-    public Tag<T> setValue(T value)
-    {
-        this.value = value;
-        return this;
-    }
-
-    /**
-     * Reads a tag from the input stream.
-     * @param dis The stream to read a tag from.
-     * @return The tag read from the stream.
-     * @throws IOException Thrown if reading from the stream failed.
-     */
-    public static Tag<?> readNamedTag(DataInput dis)
-        throws IOException
-    {
-        byte typeId = dis.readByte();
-
-        if(typeId == 0)
-        {
-            return new EndTag();
-        }
-        else
-        {
-            Tag<?> tag = newTag(typeId);
-            tag.name = dis.readUTF();
-            tag.read(dis);
-            return tag;
-        }
-    }
-
-    /**
-     * Writes a tag to the output stream.
-     * @param tag The tag to write to the stream.
-     * @param dos The stream to write to.
-     * @throws IOException Thrown if writing to the stream failed.
-     */
-    public static void writeNamedTag(Tag<?> tag, DataOutput dos)
-        throws IOException
-    {
-        dos.writeByte(tag.getId());
-        if(tag.getId() != 0)
-        {
-            dos.writeUTF(tag.getTagName());
-            tag.write(dos);
-        }
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if(!(obj instanceof Tag<?>)) return false;
-        Tag<?> tag = (Tag<?>) obj;
-        return Objects.equals(getValue(), tag.getValue());
-    }
-
-    /**
-     * Creates a new tag wrapping the specified type.
-     * @param type The type to wrap.
-     * @return The wrapped type, or null if no such wrapper exists or is possible.
-     */
-    public static Tag<?> createTagOfType(Class<?> type)
-    {
-        if (type == Byte.class)
-        {
-            return new ByteTag();
-        }
-        if (type == Short.class)
-        {
-            return new ShortTag();
-        }
-        if (type == Integer.class)
-        {
-            return new IntTag();
-        }
-        if (type == Long.class)
-        {
-            return new LongTag();
-        }
-        if (type == Float.class)
-        {
-            return new FloatTag();
-        }
-        if (type == Double.class)
-        {
-            return new DoubleTag();
-        }
-        if (type == String.class)
-        {
-            return new StringTag(
-
-            );
-        }
-
-        return null;
-    }
-
-    /**
-     * Creates a tag according to the given type ID.
-     * @param type The ID of the type of tag to create.
-     * @return The created tag, or null if the type ID doesn't match any tag types.
-     */
-    public static Tag<?> newTag(byte type) throws IOException {
-        switch(type)
-        {
-        case 0:
-            return new EndTag();
-        case 1:
-            return new ByteTag();
-        case 2:
-            return new ShortTag();
-        case 3:
-            return new IntTag();
-        case 4:
-            return new LongTag();
-        case 5:
-            return new FloatTag();
-        case 6:
-            return new DoubleTag();
-        case 7:
-            return new ByteArrayTag();
-        case 8:
-            return new StringTag();
-        case 9:
-            return new ListTag();
-        case 10:
-            return new CompoundTag();
-        case 11:
-        	return new ShortArrayTag();
-        case 12:
-        	return new DoubleArrayTag();
-        }
-        throw new CorruptedNBTException("Cannot read NBT Tag type for type '" + type + "'!");
-    }
-
-    /**
-     * Gets a string representing a tag's type.
-     * @param type The type ID corresponding to the type of tag.
-     * @return A string representing the tag type ID.
-     */
-    public static String getTagName(byte type)
-    {
-        switch(type)
-        {
-        case 0:
-            return "TAG_End";
-        case 1:
-            return "TAG_Byte";
-        case 2:
-            return "TAG_Short";
-        case 3:
-            return "TAG_Int";
-        case 4:
-            return "TAG_Long";
-        case 5:
-            return "TAG_Float";
-        case 6:
-            return "TAG_Double";
-        case 7:
-            return "TAG_Byte_Array";
-        case 8:
-            return "TAG_String";
-        case 9:
-            return "TAG_List";
-        case 10:
-            return "TAG_Compound";
-        case 11:
-        	return "TAG_Short_Array";
-        case 12:
-        	return "TAG_Double_Array";
-        }
-        return "UNKNOWN";
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlag.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlag.java
index a6c5498cd..5bcae9e0e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlag.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFlag.java
@@ -7,7 +7,7 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java
index b14e07bd4..2c79ee608 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLamp.java
@@ -17,6 +17,13 @@ public class BlockLogicLamp extends BlockLogic implements IPainted {
         isActive = isActivated;
     }
 
+    @Override
+    public void onBlockPlacedByWorld(World world, int x, int y, int z) {
+        if (isActive && !(world.hasDirectSignal(x, y, z) || world.hasNeighborSignal(x, y, z))) {
+            world.setBlockAndMetadataWithNotify(x, y, z, Blocks.LAMP_IDLE.id(), world.getBlockMetadata(x, y, z));
+        }
+    }
+
     @Override
     public void onBlockPlacedOnSide(World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
         if (world.isClientSide) {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlab.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlab.java
index e5ba5926a..4d016bb11 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlab.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSlab.java
@@ -35,10 +35,14 @@ public class BlockLogicSlab extends BlockLogic
     	super(block, Material.stone);
         this.modelBlock = modelBlock;
         this.modelBlockMetadata = modelBlockMetadata;
+        block.withLightBlock(1);
+    }
+
+    @Override
+    public void initializeBlock() {
         block.withHardness(modelBlock.blockHardness);
         block.withBlastResistance(modelBlock.blastResistance / 3F);
         block.withLightEmission(modelBlock.emission);
-        block.withLightBlock(1);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairs.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairs.java
index d17029996..32974dc56 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairs.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStairs.java
@@ -88,11 +88,15 @@ public class BlockLogicStairs extends BlockLogic
     {
         super(block, Material.stone);
         this.modelBlock = modelBlock;
-        block.withHardness(block.blockHardness);
-        block.withBlastResistance(block.blastResistance / 3F);
         block.withLightBlock(255);
     }
 
+    @Override
+    public void initializeBlock() {
+        block.withHardness(modelBlock.blockHardness);
+        block.withBlastResistance(modelBlock.blastResistance / 3F);
+    }
+
     @Override
     public @NotNull Material getMaterial() {
         return modelBlock.getMaterial();
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntity.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntity.java
index 16ffaba39..39c94be5b 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntity.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntity.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.block.entity;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.tag.BlockTags;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java
index 9f35209bb..38bd36bb4 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.block.entity;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.block.BlockLogicRotatable;
 import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.block.Block;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java
index 7f4698c60..1df720942 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java
@@ -8,8 +8,8 @@ import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.PacketBlockEntityData;
 import net.minecraft.core.util.phys.AABB;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java
index 441ee6897..8c8ab54a9 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java
@@ -9,8 +9,8 @@ import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.container.Container;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.player.inventory.InventorySorter;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.world.World;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispatcher.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispatcher.java
index e968923ec..1ee070d85 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispatcher.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispatcher.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.block.entity;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.piston.TileEntityMovingPistonBlock;
 import net.minecraft.core.util.collection.NamespaceID;
 import org.slf4j.Logger;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java
index 72aaac246..1be08e68e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java
@@ -9,8 +9,8 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.IDispensable;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.container.Container;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.world.World;
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlag.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlag.java
index 74407bb7f..62f1c4983 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlag.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlag.java
@@ -3,8 +3,8 @@ package net.minecraft.core.block.entity;
 import java.util.Random;
 import java.util.UUID;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.Items;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlowerJar.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlowerJar.java
index 2c6399051..e1d943d51 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlowerJar.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFlowerJar.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.block.entity;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicFlowerStackable;
 import net.minecraft.core.block.Blocks;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java
index 1976b97d5..5bae21bdc 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.block.entity;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.block.BlockLogicFurnace;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.motion.CarriedBlock;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlast.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlast.java
index 6bf07adcb..7fec79f08 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlast.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnaceBlast.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.block.entity;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.block.BlockLogicFurnaceBlast;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.crafting.LookupFuelFurnaceBlast;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityJukebox.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityJukebox.java
index 001f3f73c..899b505d3 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityJukebox.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityJukebox.java
@@ -6,7 +6,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.LevelListener;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.save.conversion.ChunkConverter;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 public class TileEntityJukebox extends TileEntity {
     public int record;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMeshGold.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMeshGold.java
index 59703abee..bb153de03 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMeshGold.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMeshGold.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.block.entity;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMobSpawner.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMobSpawner.java
index 09c956409..ff1e5da00 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMobSpawner.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityMobSpawner.java
@@ -5,7 +5,7 @@ import net.minecraft.core.entity.EntityDispatcher;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.phys.AABB;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.PacketSetMobSpawner;
 import org.slf4j.Logger;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityNoteblock.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityNoteblock.java
index 342f815df..df4e9b66d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityNoteblock.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityNoteblock.java
@@ -2,7 +2,7 @@ package net.minecraft.core.block.entity;
 
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.BlockLogicNote;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.util.helper.MathHelper;
 
 @Deprecated
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySeat.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySeat.java
index e8f32984e..62d64220e 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySeat.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySeat.java
@@ -6,7 +6,7 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.IVehicle;
 import net.minecraft.core.world.World;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 public class TileEntitySeat
     extends TileEntity
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySign.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySign.java
index c73f70ef3..868556838 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySign.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySign.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.block.entity;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumSignPicture;
 import net.minecraft.core.net.command.TextFormatting;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java
index 0df117025..e0d3ef1e1 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java
@@ -2,8 +2,8 @@ package net.minecraft.core.block.entity;
 
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.BlockLogicChest;
 import net.minecraft.core.block.BlockLogicTrommel;
diff --git a/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java b/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java
index ac6113479..62c060903 100644
--- a/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/block/motion/CarriedBlock.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.block.motion;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityDispatcher;
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java b/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java
index f2e3b4510..e35cbd94d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java
@@ -7,7 +7,7 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.phys.AABB;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRule.java b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRule.java
index 5f5aebc4a..62530693d 100644
--- a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRule.java
+++ b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRule.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.data.gamerule;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 public abstract class GameRule<T>
 {
diff --git a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleBoolean.java b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleBoolean.java
index 6f9279c31..dc581317d 100644
--- a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleBoolean.java
+++ b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleBoolean.java
@@ -1,8 +1,8 @@
 package net.minecraft.core.data.gamerule;
 
-import com.mojang.nbt.ByteTag;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.Tag;
+import com.mojang.nbt.tags.ByteTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.Tag;
 
 public class GameRuleBoolean
     extends GameRule<Boolean>
diff --git a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleCollection.java b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleCollection.java
index 4d6239148..96b4ea68b 100644
--- a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleCollection.java
+++ b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleCollection.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.data.gamerule;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.data.registry.Registries;
 
 import java.util.HashMap;
diff --git a/game/core/src/main/java/net/minecraft/core/data/registry/Registry.java b/game/core/src/main/java/net/minecraft/core/data/registry/Registry.java
index 8d60f5fe5..1d4331d20 100644
--- a/game/core/src/main/java/net/minecraft/core/data/registry/Registry.java
+++ b/game/core/src/main/java/net/minecraft/core/data/registry/Registry.java
@@ -1,8 +1,8 @@
 package net.minecraft.core.data.registry;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.IntTag;
-import com.mojang.nbt.Tag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.IntTag;
+import com.mojang.nbt.tags.Tag;
 
 import java.util.*;
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/Entity.java b/game/core/src/main/java/net/minecraft/core/entity/Entity.java
index 7bf09ecd0..891998c27 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/Entity.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/Entity.java
@@ -10,10 +10,10 @@ import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.world.ICarriable;
 import org.jetbrains.annotations.Nullable;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.DoubleTag;
-import com.mojang.nbt.FloatTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.DoubleTag;
+import com.mojang.nbt.tags.FloatTag;
+import com.mojang.nbt.tags.ListTag;
 
 import net.minecraft.core.Global;
 import net.minecraft.core.block.Block;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java b/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
index d1fe54ece..4bdc17452 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
@@ -6,7 +6,7 @@ import net.minecraft.core.entity.monster.*;
 import net.minecraft.core.entity.projectile.*;
 import net.minecraft.core.entity.vehicle.EntityBoat;
 import net.minecraft.core.entity.vehicle.MinecartEntity;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java b/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java
index 953aa3d2e..5164a6c36 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java
@@ -10,7 +10,7 @@ import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.IVehicle;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java b/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java
index 8d08c9732..118678eb8 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java
@@ -7,7 +7,7 @@ import net.minecraft.core.achievement.stat.StatList;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.material.Material;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java b/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java
index cccec28aa..d5e612649 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java
@@ -2,7 +2,7 @@ package net.minecraft.core.entity;
 
 import java.util.List;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.achievement.stat.StatList;
 import net.minecraft.core.block.Block;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java b/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java
index 037fa0d1e..8065ecb8f 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java
@@ -5,7 +5,7 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.util.phys.Vec3;
 import net.minecraft.core.world.World;
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java b/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java
index dd913e88f..d99a8254d 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java
@@ -7,7 +7,7 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.material.Material;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityPrimedTNT.java b/game/core/src/main/java/net/minecraft/core/entity/EntityPrimedTNT.java
index 9268ef57f..6356377f5 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityPrimedTNT.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityPrimedTNT.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.entity;
 
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 
 public class EntityPrimedTNT extends Entity
diff --git a/game/core/src/main/java/net/minecraft/core/entity/Mob.java b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
index f0b2abdcc..468f9c369 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/Mob.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.entity;
 
 import com.b100.utils.StringUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.Global;
 import net.minecraft.core.item.ItemFood;
 import net.minecraft.core.util.phys.HitResult;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobAnimal.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobAnimal.java
index 65a54063d..d55b3b453 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobAnimal.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobAnimal.java
@@ -5,7 +5,7 @@ import net.minecraft.core.entity.MobPathfinder;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.season.Seasons;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobChicken.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobChicken.java
index 90015196e..e62402866 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobChicken.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobChicken.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.entity.animal;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.WeightedRandomLootObject;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.Items;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobCow.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobCow.java
index 9bd83a11d..e44c590cd 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobCow.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobCow.java
@@ -5,7 +5,7 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemBucketEmpty;
 import net.minecraft.core.item.ItemStack;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.item.tag.ItemTags;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.world.World;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java
index e3b5637cd..3d1ac5065 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.entity.animal;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.Entity;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java
index 25fb24f0c..18afd45c6 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java
@@ -9,7 +9,7 @@ import net.minecraft.core.entity.monster.MobZombiePig;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.Items;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.world.World;
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java
index 77d962d46..998a5d2bf 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.entity.animal;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.tag.BlockTags;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWaterAnimal.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWaterAnimal.java
index 274466abc..1b36abc41 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWaterAnimal.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWaterAnimal.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.entity.animal;
 
 import net.minecraft.core.entity.MobPathfinder;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 
 public class MobWaterAnimal extends MobPathfinder
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
index b8b6b4bd7..53ed77784 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
@@ -14,7 +14,7 @@ import net.minecraft.core.item.material.ArmorMaterial;
 import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.pathfinder.Path;
 import net.minecraft.core.world.World;
 import net.minecraft.core.util.phys.AABB;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobCreeper.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobCreeper.java
index 8093cebb4..ed8a1bb06 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobCreeper.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobCreeper.java
@@ -4,7 +4,7 @@ import net.minecraft.core.WeightedRandomLootObject;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityLightning;
 import net.minecraft.core.item.Items;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.world.World;
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
index bfaf359bf..9f52997d9 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
@@ -284,4 +284,14 @@ public class MobGhast extends MobFlying
     {
         return 1;
     }
+
+    @Override
+    public float getBrightness(float partialTick) {
+        return 1;
+    }
+
+    @Override
+    public int getLightmapCoord(float partialTick) {
+        return world.getLightmapCoord(15, 15);
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobHuman.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobHuman.java
index ba0fdbd85..cf121e781 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobHuman.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobHuman.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.entity.monster;
 
 import net.minecraft.core.entity.Entity;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.util.helper.GetMonsterSkinUrlThread;
 import net.minecraft.core.world.World;
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonster.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonster.java
index 4d70e795c..39291d183 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonster.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonster.java
@@ -5,7 +5,7 @@ import net.minecraft.core.entity.MobPathfinder;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.util.phys.Vec3;
 import net.minecraft.core.world.World;
 import net.minecraft.core.util.helper.DamageType;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobScorpion.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobScorpion.java
index bd515e69a..baa8b5da6 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobScorpion.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobScorpion.java
@@ -6,7 +6,7 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.item.Items;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 
 public class MobScorpion extends MobMonster
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java
index 84de94046..f3ae7a779 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java
@@ -7,7 +7,7 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.weather.Weathers;
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSlime.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSlime.java
index 10a5f2cb2..244164d3e 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSlime.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSlime.java
@@ -6,7 +6,7 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.util.helper.DamageType;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSpider.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSpider.java
index 512eef413..2700d52e5 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSpider.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSpider.java
@@ -6,7 +6,7 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 
 public class MobSpider extends MobMonster
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombieArmored.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombieArmored.java
index 78a29b630..7302afbac 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombieArmored.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombieArmored.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.entity.monster;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.item.Items;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java
index 1e6c85ec7..060108046 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java
@@ -11,7 +11,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.util.helper.DamageType;
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
index 630c8cbe9..9dd3683b9 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.entity.player;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.block.BlockLogicBed;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.entity.TileEntitySign;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/projectile/Projectile.java b/game/core/src/main/java/net/minecraft/core/entity/projectile/Projectile.java
index 6c3e178ef..c9542a91f 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/projectile/Projectile.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/projectile/Projectile.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.entity.projectile;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.util.phys.HitResult;
 import net.minecraft.core.entity.Entity;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java
index 9f68bc9d9..654a75d49 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.entity.projectile;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.entity.player.Player;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityBoat.java b/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityBoat.java
index 8c97a350c..5d3b378a8 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityBoat.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityBoat.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.entity.vehicle;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityFlag;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java b/game/core/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
index 5fd66e042..50c90b2b7 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.entity.vehicle;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicRail;
 import net.minecraft.core.block.Blocks;
diff --git a/game/core/src/main/java/net/minecraft/core/item/Item.java b/game/core/src/main/java/net/minecraft/core/item/Item.java
index 1f51d14a9..6e554988a 100644
--- a/game/core/src/main/java/net/minecraft/core/item/Item.java
+++ b/game/core/src/main/java/net/minecraft/core/item/Item.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.item;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.achievement.stat.Stat;
 import net.minecraft.core.achievement.stat.StatItem;
 import net.minecraft.core.achievement.stat.StatList;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemFlag.java b/game/core/src/main/java/net/minecraft/core/item/ItemFlag.java
index 70c0d2f9f..325383700 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemFlag.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemFlag.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.item;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityFlag;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemPaintBrush.java b/game/core/src/main/java/net/minecraft/core/item/ItemPaintBrush.java
index f3a75adf5..8f57e967f 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemPaintBrush.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemPaintBrush.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.item;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.IPaintable;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemStack.java b/game/core/src/main/java/net/minecraft/core/item/ItemStack.java
index b341462d1..aea19a0c6 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemStack.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemStack.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.item;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.Global;
 import net.minecraft.core.achievement.stat.StatList;
 import net.minecraft.core.block.Block;
diff --git a/game/core/src/main/java/net/minecraft/core/net/SavedServerList.java b/game/core/src/main/java/net/minecraft/core/net/SavedServerList.java
index 84fbeeaf3..42442f3cb 100644
--- a/game/core/src/main/java/net/minecraft/core/net/SavedServerList.java
+++ b/game/core/src/main/java/net/minecraft/core/net/SavedServerList.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.net;
 
-import com.mojang.nbt.Tag;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.Tag;
+import com.mojang.nbt.tags.CompoundTag;
 
 import java.io.*;
 import java.nio.file.Files;
diff --git a/game/core/src/main/java/net/minecraft/core/net/ServerData.java b/game/core/src/main/java/net/minecraft/core/net/ServerData.java
index 9caef981d..f0e541cf5 100644
--- a/game/core/src/main/java/net/minecraft/core/net/ServerData.java
+++ b/game/core/src/main/java/net/minecraft/core/net/ServerData.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.net;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 public class ServerData
 {
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandClear.java b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandClear.java
index 1ef4da227..3fbca8803 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandClear.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandClear.java
@@ -6,7 +6,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
 import com.mojang.brigadier.builder.RequiredArgumentBuilder;
 import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.Tag;
+import com.mojang.nbt.tags.Tag;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandClone.java b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandClone.java
index b46e3ea43..b8c81d737 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandClone.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandClone.java
@@ -7,7 +7,7 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder;
 import com.mojang.brigadier.context.CommandContext;
 import com.mojang.brigadier.exceptions.CommandSyntaxException;
 import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.net.command.CommandManager;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandFill.java b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandFill.java
index eff487e24..c741b7708 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandFill.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandFill.java
@@ -4,7 +4,7 @@ import com.mojang.brigadier.CommandDispatcher;
 import com.mojang.brigadier.builder.LiteralArgumentBuilder;
 import com.mojang.brigadier.builder.RequiredArgumentBuilder;
 import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.net.command.CommandManager;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTestFor.java b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTestFor.java
index 4eb2116cb..9e5398f11 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTestFor.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTestFor.java
@@ -4,7 +4,7 @@ import com.mojang.brigadier.Command;
 import com.mojang.brigadier.CommandDispatcher;
 import com.mojang.brigadier.builder.LiteralArgumentBuilder;
 import com.mojang.brigadier.builder.RequiredArgumentBuilder;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.Entity;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/ArgumentParser.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/ArgumentParser.java
index 3ea6759d9..d14bbb55f 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/ArgumentParser.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/ArgumentParser.java
@@ -4,7 +4,7 @@ import com.mojang.brigadier.StringReader;
 import com.mojang.brigadier.exceptions.CommandSyntaxException;
 import com.mojang.brigadier.suggestion.Suggestions;
 import com.mojang.brigadier.suggestion.SuggestionsBuilder;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.net.command.exceptions.CommandExceptions;
 import net.minecraft.core.net.command.util.CommandHelper;
 import net.minecraft.core.net.command.util.NbtHelper;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockArgumentParser.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockArgumentParser.java
index 281c9df23..12d7d9bbb 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockArgumentParser.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockArgumentParser.java
@@ -5,7 +5,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
 import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
 import com.mojang.brigadier.suggestion.Suggestions;
 import com.mojang.brigadier.suggestion.SuggestionsBuilder;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.lang.I18n;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockInput.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockInput.java
index 1a1dd7e01..da9aa302b 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockInput.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/BlockInput.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.net.command.helpers;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.Block;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/EntitySelectorOptions.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/EntitySelectorOptions.java
index 10fce3b60..c5dad2470 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/EntitySelectorOptions.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/EntitySelectorOptions.java
@@ -5,8 +5,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
 import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
 import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
 import com.mojang.brigadier.suggestion.SuggestionsBuilder;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.Tag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.Tag;
 import net.minecraft.core.lang.text.ChainText;
 import net.minecraft.core.lang.text.Text;
 import net.minecraft.core.entity.Entity;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/ItemStackArgumentParser.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/ItemStackArgumentParser.java
index e54c86d42..7625d23ac 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/ItemStackArgumentParser.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/ItemStackArgumentParser.java
@@ -5,7 +5,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
 import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
 import com.mojang.brigadier.suggestion.Suggestions;
 import com.mojang.brigadier.suggestion.SuggestionsBuilder;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.lang.I18n;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/util/BeautifulNbt.java b/game/core/src/main/java/net/minecraft/core/net/command/util/BeautifulNbt.java
index 6907afe06..cbbe8b1e3 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/util/BeautifulNbt.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/util/BeautifulNbt.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.net.command.util;
 
-import com.mojang.nbt.*;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.Tag;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.List;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/util/CommandHelper.java b/game/core/src/main/java/net/minecraft/core/net/command/util/CommandHelper.java
index 1a4cd1151..1c8a08542 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/util/CommandHelper.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/util/CommandHelper.java
@@ -3,8 +3,8 @@ package net.minecraft.core.net.command.util;
 import com.mojang.brigadier.exceptions.CommandSyntaxException;
 import com.mojang.brigadier.suggestion.Suggestions;
 import com.mojang.brigadier.suggestion.SuggestionsBuilder;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.Tag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.Tag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/util/NbtHelper.java b/game/core/src/main/java/net/minecraft/core/net/command/util/NbtHelper.java
index 487d2eecd..6fb79088c 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/util/NbtHelper.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/util/NbtHelper.java
@@ -2,7 +2,19 @@ package net.minecraft.core.net.command.util;
 
 import com.mojang.brigadier.StringReader;
 import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import com.mojang.nbt.*;
+import com.mojang.nbt.tags.ByteArrayTag;
+import com.mojang.nbt.tags.ByteTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.DoubleArrayTag;
+import com.mojang.nbt.tags.DoubleTag;
+import com.mojang.nbt.tags.FloatTag;
+import com.mojang.nbt.tags.IntTag;
+import com.mojang.nbt.tags.ListTag;
+import com.mojang.nbt.tags.LongTag;
+import com.mojang.nbt.tags.ShortArrayTag;
+import com.mojang.nbt.tags.ShortTag;
+import com.mojang.nbt.tags.StringTag;
+import com.mojang.nbt.tags.Tag;
 import net.minecraft.core.net.command.exceptions.CommandExceptions;
 
 import java.util.ArrayList;
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/Packet.java b/game/core/src/main/java/net/minecraft/core/net/packet/Packet.java
index 371cfb9f0..794210e07 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/Packet.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/Packet.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.net.packet;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.Global;
 import net.minecraft.core.net.handler.PacketHandler;
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketAddItemEntity.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketAddItemEntity.java
index 585a4bf9d..399e8911b 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketAddItemEntity.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketAddItemEntity.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.net.packet;
 
 import net.minecraft.core.entity.EntityItem;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.net.handler.PacketHandler;
 import net.minecraft.core.util.helper.MathHelper;
 
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketAddPlayer.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketAddPlayer.java
index 3b46a20ae..600b8f0be 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketAddPlayer.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketAddPlayer.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.net.packet;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.net.handler.PacketHandler;
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketBlockEntityData.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketBlockEntityData.java
index 271cdc35a..2c388caa0 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketBlockEntityData.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketBlockEntityData.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.net.packet;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.net.handler.PacketHandler;
 
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerSetContent.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerSetContent.java
index 82870c956..70df42e9f 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerSetContent.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerSetContent.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.net.packet;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.net.handler.PacketHandler;
 
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerSetSlot.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerSetSlot.java
index 3f8590dcd..8628ab476 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerSetSlot.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerSetSlot.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.net.packet;
 
 import net.minecraft.core.item.ItemStack;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.net.handler.PacketHandler;
 
 import java.io.*;
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketEntityTagData.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketEntityTagData.java
index f387667b3..37d71fedc 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketEntityTagData.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketEntityTagData.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.net.packet;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.net.handler.PacketHandler;
 
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketGameRule.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketGameRule.java
index 7c8f94a3c..0d39fafeb 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketGameRule.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketGameRule.java
@@ -4,7 +4,7 @@ import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 import net.minecraft.core.data.gamerule.GameRuleCollection;
 import net.minecraft.core.net.handler.PacketHandler;
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketSetEquippedItem.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketSetEquippedItem.java
index 55c7e1a41..87b2b88a5 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketSetEquippedItem.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketSetEquippedItem.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.net.packet;
 
 import net.minecraft.core.item.ItemStack;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.net.handler.PacketHandler;
 
 import java.io.*;
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketSetHeldObject.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketSetHeldObject.java
index f89168aa7..a16e7111d 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketSetHeldObject.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketSetHeldObject.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.net.packet;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.net.handler.PacketHandler;
 import net.minecraft.core.world.ICarriable;
 import org.jetbrains.annotations.Nullable;
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java
index 4c7bfb860..c843954af 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java
@@ -1,8 +1,8 @@
 package net.minecraft.core.player.inventory.container;
 
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
diff --git a/game/core/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java b/game/core/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java
index 9c763bb47..efe5bfa2d 100644
--- a/game/core/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java
+++ b/game/core/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java
@@ -3,7 +3,7 @@ package net.minecraft.core.util.helper;
 import com.b100.json.JsonParser;
 import com.b100.json.element.JsonObject;
 import com.b100.utils.StringUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/ICarriable.java b/game/core/src/main/java/net/minecraft/core/world/ICarriable.java
index 44a8f4db6..a7aefa966 100644
--- a/game/core/src/main/java/net/minecraft/core/world/ICarriable.java
+++ b/game/core/src/main/java/net/minecraft/core/world/ICarriable.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.block.motion.CarriedBlock;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.Side;
diff --git a/game/core/src/main/java/net/minecraft/core/world/World.java b/game/core/src/main/java/net/minecraft/core/world/World.java
index 438515f37..15b0c607b 100644
--- a/game/core/src/main/java/net/minecraft/core/world/World.java
+++ b/game/core/src/main/java/net/minecraft/core/world/World.java
@@ -13,7 +13,7 @@ import java.util.TreeSet;
 import java.util.UUID;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.EntityItem;
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java
index 8775c43a0..8069fefad 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java
@@ -6,9 +6,9 @@ import net.minecraft.core.block.entity.TileEntityDispatcher;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityDispatcher;
-import com.mojang.nbt.Tag;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.Tag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.chunk.reader.ChunkReader;
 import net.minecraft.core.world.chunk.reader.ChunkReaderLegacy;
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java
index afa6a2ee5..ce0350e51 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java
@@ -1,8 +1,8 @@
 package net.minecraft.core.world.chunk;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.CorruptedNBTException;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.UnknownTagException;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.save.LevelData;
 import net.minecraft.core.world.save.mcregion.RegionFileCache;
@@ -36,7 +36,7 @@ public class ChunkLoaderRegion
             } catch (ZipException zipException) {
                 LOGGER.warn("Zipped data for chunk at {}, {} is too corrupted to read! Assuming unrecoverable and resetting!", x, z, zipException);
                 return null;
-            } catch (CorruptedNBTException corruptedNBTException){
+            } catch (UnknownTagException corruptedNBTException){
                 LOGGER.warn("NBT data for chunk at {}, {} is too corrupted to read! Assuming unrecoverable and resetting!", x, z, corruptedNBTException);
                 return null;
             }
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReader.java b/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReader.java
index 75a371da3..d6c98202a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReader.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReader.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.chunk.reader;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.data.ChunkNibbleArray;
 import net.minecraft.core.world.data.ChunkUnsignedByteArray;
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderLegacy.java b/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderLegacy.java
index 6c755740e..f5a5f6751 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderLegacy.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderLegacy.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.chunk.reader;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.world.chunk.ChunkSection;
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderVersion1.java b/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderVersion1.java
index a15c1f7cc..d7679969a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderVersion1.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderVersion1.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.chunk.reader;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.data.registry.Registry;
 import net.minecraft.core.world.World;
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderVersion2.java b/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderVersion2.java
index 56ebfc663..5c921eaa3 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderVersion2.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/reader/ChunkReaderVersion2.java
@@ -1,8 +1,8 @@
 package net.minecraft.core.world.chunk.reader;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
-import com.mojang.nbt.Tag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
+import com.mojang.nbt.tags.Tag;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.data.registry.Registry;
 import net.minecraft.core.world.World;
diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/writer/ChunkWriter.java b/game/core/src/main/java/net/minecraft/core/world/chunk/writer/ChunkWriter.java
index 616c73f78..7b577d987 100644
--- a/game/core/src/main/java/net/minecraft/core/world/chunk/writer/ChunkWriter.java
+++ b/game/core/src/main/java/net/minecraft/core/world/chunk/writer/ChunkWriter.java
@@ -1,8 +1,8 @@
 package net.minecraft.core.world.chunk.writer;
 
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
-import com.mojang.nbt.Tag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
+import com.mojang.nbt.tags.Tag;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.data.registry.Registry;
 import net.minecraft.core.world.World;
diff --git a/game/core/src/main/java/net/minecraft/core/world/config/spawning/SpawnerConfig.java b/game/core/src/main/java/net/minecraft/core/world/config/spawning/SpawnerConfig.java
index c6aeccc92..fb153d8ad 100644
--- a/game/core/src/main/java/net/minecraft/core/world/config/spawning/SpawnerConfig.java
+++ b/game/core/src/main/java/net/minecraft/core/world/config/spawning/SpawnerConfig.java
@@ -1,9 +1,9 @@
 package net.minecraft.core.world.config.spawning;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.ByteTag;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.Tag;
+import com.mojang.nbt.tags.ByteTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.Tag;
 import net.minecraft.core.util.HardIllegalArgumentException;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.world.World;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/DimensionData.java b/game/core/src/main/java/net/minecraft/core/world/save/DimensionData.java
index 6cebaa0c3..a9f3c7541 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/DimensionData.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/DimensionData.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.save;
 
-import com.mojang.nbt.ByteTag;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.ByteTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.data.legacy.LegacyWorldTypes;
 import net.minecraft.core.data.registry.Registries;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/ISaveConverter.java b/game/core/src/main/java/net/minecraft/core/world/save/ISaveConverter.java
index 72c7eaaf2..9253bdb4d 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/ISaveConverter.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/ISaveConverter.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.save;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.ProgressListener;
 
 import java.io.File;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/ISaveFormat.java b/game/core/src/main/java/net/minecraft/core/world/save/ISaveFormat.java
index 096ebe77b..1aba0dcde 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/ISaveFormat.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/ISaveFormat.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.save;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.Dimension;
 
 import java.io.File;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/LevelData.java b/game/core/src/main/java/net/minecraft/core/world/save/LevelData.java
index 9277ba43b..b1e00bbfd 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/LevelData.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/LevelData.java
@@ -4,7 +4,7 @@ import com.mojang.logging.LogUtils;
 import net.minecraft.core.enums.Difficulty;
 import net.minecraft.core.data.gamerule.GameRuleCollection;
 import net.minecraft.core.entity.player.Player;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.config.spawning.SpawnerConfig;
 import org.jetbrains.annotations.NotNull;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/LevelStorage.java b/game/core/src/main/java/net/minecraft/core/world/save/LevelStorage.java
index 9cf4b34df..f09593fce 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/LevelStorage.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/LevelStorage.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.save;
 
 import net.minecraft.core.entity.player.Player;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.chunk.IChunkLoader;
 import net.minecraft.core.world.Dimension;
 import java.io.File;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java b/game/core/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java
index 6a315fcb0..e1c6a2cf4 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java
@@ -3,7 +3,7 @@ package net.minecraft.core.world.save;
 import com.mojang.logging.LogUtils;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.helper.MathHelper;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.Dimension;
 import org.slf4j.Logger;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/SaveHandlerBase.java b/game/core/src/main/java/net/minecraft/core/world/save/SaveHandlerBase.java
index f9686ecb6..b0b2405af 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/SaveHandlerBase.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/SaveHandlerBase.java
@@ -3,7 +3,7 @@ package net.minecraft.core.world.save;
 import com.mojang.logging.LogUtils;
 import net.minecraft.core.MinecraftException;
 import net.minecraft.core.entity.player.Player;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.chunk.ChunkLoaderLegacy;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/SaveHandlerServer.java b/game/core/src/main/java/net/minecraft/core/world/save/SaveHandlerServer.java
index d6c68b811..4fab0e346 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/SaveHandlerServer.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/SaveHandlerServer.java
@@ -2,7 +2,7 @@ package net.minecraft.core.world.save;
 
 import com.mojang.logging.LogUtils;
 import net.minecraft.core.entity.player.Player;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.chunk.IChunkLoader;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.Dimension;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19132To19133.java b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19132To19133.java
index 0674d27fe..d2c56cabd 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19132To19133.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19132To19133.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.save.conversion;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.ProgressListener;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19133To19134.java b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19133To19134.java
index 4f278edf6..89ca0dda9 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19133To19134.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19133To19134.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.save.conversion;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.data.legacy.LegacyWorldTypes;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.ProgressListener;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterLegacyTo19132.java b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterLegacyTo19132.java
index b3df2469a..075b31c56 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterLegacyTo19132.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterLegacyTo19132.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.save.conversion;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.data.legacy.LegacyWorldTypes;
 import net.minecraft.core.world.ProgressListener;
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterMCRegionBase.java b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterMCRegionBase.java
index 4aac46f4d..37f5bae97 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterMCRegionBase.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterMCRegionBase.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.save.conversion;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.ProgressListener;
 import net.minecraft.core.world.save.ISaveConverter;
diff --git a/game/core/src/main/java/net/minecraft/core/world/saveddata/SavedData.java b/game/core/src/main/java/net/minecraft/core/world/saveddata/SavedData.java
index 827fe0528..18baf642e 100644
--- a/game/core/src/main/java/net/minecraft/core/world/saveddata/SavedData.java
+++ b/game/core/src/main/java/net/minecraft/core/world/saveddata/SavedData.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.saveddata;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 public abstract class SavedData
 {
diff --git a/game/core/src/main/java/net/minecraft/core/world/saveddata/SavedDataStorage.java b/game/core/src/main/java/net/minecraft/core/world/saveddata/SavedDataStorage.java
index d1558df66..0116f218e 100644
--- a/game/core/src/main/java/net/minecraft/core/world/saveddata/SavedDataStorage.java
+++ b/game/core/src/main/java/net/minecraft/core/world/saveddata/SavedDataStorage.java
@@ -1,9 +1,9 @@
 package net.minecraft.core.world.saveddata;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.Tag;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ShortTag;
+import com.mojang.nbt.tags.Tag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ShortTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.save.LevelStorage;
 import org.slf4j.Logger;
diff --git a/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java b/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java
index a32faab15..92db2c965 100644
--- a/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java
+++ b/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java
@@ -4,8 +4,8 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityFlag;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
-import com.mojang.nbt.CompoundTag;
-import com.mojang.nbt.ListTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.saveddata.SavedData;
diff --git a/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/MapWaypoint.java b/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/MapWaypoint.java
index e769dd621..db053e1c0 100644
--- a/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/MapWaypoint.java
+++ b/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/MapWaypoint.java
@@ -1,6 +1,6 @@
 package net.minecraft.core.world.saveddata.maps;
 
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
diff --git a/game/core/src/main/resources/assets/minecraft/sounds/sounds.json b/game/core/src/main/resources/assets/minecraft/sounds/sounds.json
index 4b311630a..c54fdb2cf 100644
--- a/game/core/src/main/resources/assets/minecraft/sounds/sounds.json
+++ b/game/core/src/main/resources/assets/minecraft/sounds/sounds.json
@@ -44,6 +44,12 @@
       "random/door_open.ogg"
     ]
   },
+  "random.achievement": {
+    "sounds": [
+      "random/achievement1.ogg",
+      "random/achievement2.ogg"
+    ]
+  },
   "random.bite": {
     "subtitle": "subtitles.random.bite",
     "sounds": [
diff --git a/game/server/build.gradle.kts b/game/server/build.gradle.kts
index c16e586bb..2d965b857 100644
--- a/game/server/build.gradle.kts
+++ b/game/server/build.gradle.kts
@@ -25,6 +25,8 @@ dependencies {
     implementation(libs.gson)?.let { include(it) }
     implementation(libs.brigadier)?.let { include(it) }
     implementation(libs.bundles.log4j)?.let { include(it) }
+    implementation(project(":util:nbt"))?.let { include(it) }
+    implementation(project(":util:logging"))?.let { include(it) }
     // </core dependencies>
 }
 
diff --git a/game/server/src/main/java/net/minecraft/server/MinecraftServer.java b/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
index f2359f95d..0a37607a5 100644
--- a/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2,7 +2,7 @@ package net.minecraft.server;
 
 import com.mojang.brigadier.exceptions.CommandSyntaxException;
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.Global;
 import net.minecraft.core.MinecraftAccessor;
 import net.minecraft.core.achievement.stat.StatList;
diff --git a/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java b/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java
index aefb04f7f..cac8ecec3 100644
--- a/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java
+++ b/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java
@@ -13,7 +13,7 @@ import net.minecraft.core.item.Item;
 import net.minecraft.core.item.IComplexItem;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.lang.I18n;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.net.command.TextFormatting;
 import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.player.inventory.menu.*;
diff --git a/game/server/src/main/java/net/minecraft/server/player/PlayerManager.java b/game/server/src/main/java/net/minecraft/server/player/PlayerManager.java
index 741d6918a..d57432252 100644
--- a/game/server/src/main/java/net/minecraft/server/player/PlayerManager.java
+++ b/game/server/src/main/java/net/minecraft/server/player/PlayerManager.java
@@ -4,7 +4,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 import com.mojang.logging.LogUtils;
-import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.net.packet.*;
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 54db8e0a2..e0ae3ae5f 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -6,3 +6,7 @@ include("util:stellar")
 include("util:datagen")
 include("util:seed-viewer")
 findProject(":util:seed-viewer")?.name = "seed-viewer"
+include("util:nbt")
+findProject(":util:nbt")?.name = "nbt"
+include("util:logging")
+findProject(":util:logging")?.name = "logging"
diff --git a/util/logging/.gitignore b/util/logging/.gitignore
new file mode 100644
index 000000000..c795b054e
--- /dev/null
+++ b/util/logging/.gitignore
@@ -0,0 +1 @@
+build
\ No newline at end of file
diff --git a/util/logging/build.gradle.kts b/util/logging/build.gradle.kts
new file mode 100644
index 000000000..ee3683f2a
--- /dev/null
+++ b/util/logging/build.gradle.kts
@@ -0,0 +1,31 @@
+plugins {
+    id("java")
+}
+
+group = "com.mojang"
+version = "1.0.0"
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    testImplementation(platform("org.junit:junit-bom:5.10.0"))
+    testImplementation("org.junit.jupiter:junit-jupiter")
+
+    implementation(libs.jetbrains.annotations)
+    implementation(libs.bundles.log4j)
+}
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_1_8
+    targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+tasks.withType(Jar::class.java) {
+    dependsOn(tasks.test)
+}
+
+tasks.test {
+    useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/game/core/src/main/java/com/mojang/logging/LogQueues.java b/util/logging/src/main/java/com/mojang/logging/LogQueues.java
similarity index 100%
rename from game/core/src/main/java/com/mojang/logging/LogQueues.java
rename to util/logging/src/main/java/com/mojang/logging/LogQueues.java
diff --git a/game/core/src/main/java/com/mojang/logging/LogUtils.java b/util/logging/src/main/java/com/mojang/logging/LogUtils.java
similarity index 100%
rename from game/core/src/main/java/com/mojang/logging/LogUtils.java
rename to util/logging/src/main/java/com/mojang/logging/LogUtils.java
diff --git a/game/core/src/main/java/com/mojang/logging/annotations/FieldsAreNonnullByDefault.java b/util/logging/src/main/java/com/mojang/logging/annotations/FieldsAreNonnullByDefault.java
similarity index 100%
rename from game/core/src/main/java/com/mojang/logging/annotations/FieldsAreNonnullByDefault.java
rename to util/logging/src/main/java/com/mojang/logging/annotations/FieldsAreNonnullByDefault.java
diff --git a/game/core/src/main/java/com/mojang/logging/annotations/MethodsReturnNonnullByDefault.java b/util/logging/src/main/java/com/mojang/logging/annotations/MethodsReturnNonnullByDefault.java
similarity index 100%
rename from game/core/src/main/java/com/mojang/logging/annotations/MethodsReturnNonnullByDefault.java
rename to util/logging/src/main/java/com/mojang/logging/annotations/MethodsReturnNonnullByDefault.java
diff --git a/game/core/src/main/java/com/mojang/logging/plugins/LegacyXMLLayout.java b/util/logging/src/main/java/com/mojang/logging/plugins/LegacyXMLLayout.java
similarity index 100%
rename from game/core/src/main/java/com/mojang/logging/plugins/LegacyXMLLayout.java
rename to util/logging/src/main/java/com/mojang/logging/plugins/LegacyXMLLayout.java
diff --git a/game/core/src/main/java/com/mojang/logging/plugins/QueueLogAppender.java b/util/logging/src/main/java/com/mojang/logging/plugins/QueueLogAppender.java
similarity index 100%
rename from game/core/src/main/java/com/mojang/logging/plugins/QueueLogAppender.java
rename to util/logging/src/main/java/com/mojang/logging/plugins/QueueLogAppender.java
diff --git a/util/nbt/.gitignore b/util/nbt/.gitignore
new file mode 100644
index 000000000..6ca7a5037
--- /dev/null
+++ b/util/nbt/.gitignore
@@ -0,0 +1,2 @@
+build
+testWork
\ No newline at end of file
diff --git a/util/nbt/build.gradle.kts b/util/nbt/build.gradle.kts
new file mode 100644
index 000000000..bf526f429
--- /dev/null
+++ b/util/nbt/build.gradle.kts
@@ -0,0 +1,34 @@
+plugins {
+    id("java")
+}
+
+group = "com.mojang"
+version = "1.1.0"
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    testImplementation(platform("org.junit:junit-bom:5.10.0"))
+    testImplementation("org.junit.jupiter:junit-jupiter")
+
+    implementation(libs.jetbrains.annotations)
+}
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_1_8
+    targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+tasks.withType(Jar::class.java) {
+    dependsOn(tasks.test)
+}
+
+tasks.withType(JavaExec::class.java) {
+    dependsOn(tasks.test)
+}
+
+tasks.test {
+    useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/game/core/src/main/java/com/mojang/nbt/NbtIo.java b/util/nbt/src/main/java/com/mojang/nbt/NbtIo.java
similarity index 61%
rename from game/core/src/main/java/com/mojang/nbt/NbtIo.java
rename to util/nbt/src/main/java/com/mojang/nbt/NbtIo.java
index c062eb1c1..c4b20110e 100644
--- a/game/core/src/main/java/com/mojang/nbt/NbtIo.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/NbtIo.java
@@ -1,11 +1,16 @@
 package com.mojang.nbt;
 
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.Tag;
+import org.jetbrains.annotations.NotNull;
+
 import java.io.*;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
 public class NbtIo
 {
+    @SuppressWarnings("unused")
     public static CompoundTag readCompressed(InputStream inputStream)
         throws IOException
     {
@@ -15,7 +20,8 @@ public class NbtIo
         }
     }
 
-    public static void writeCompressed(CompoundTag tag, OutputStream outputStream)
+    @SuppressWarnings("unused")
+    public static void writeCompressed(@NotNull CompoundTag tag, OutputStream outputStream)
         throws IOException
     {
         try (DataOutputStream dataoutputstream = new DataOutputStream(new GZIPOutputStream(outputStream)))
@@ -24,21 +30,19 @@ public class NbtIo
         }
     }
 
-    public static CompoundTag read(DataInput dataInput)
+    @SuppressWarnings("unused")
+    public static @NotNull CompoundTag read(DataInput dataInput)
         throws IOException
     {
         Tag<?> tag = Tag.readNamedTag(dataInput);
-        if (tag instanceof CompoundTag)
-        {
-            return (CompoundTag) tag;
-        }
-        else
-        {
+        if (!(tag instanceof CompoundTag)) {
             throw new IOException("Root tag must be a named compound tag!");
         }
+        return (CompoundTag) tag;
     }
 
-    public static void write(CompoundTag tag, DataOutput dataOutput)
+    @SuppressWarnings("unused")
+    public static void write(@NotNull CompoundTag tag, DataOutput dataOutput)
         throws IOException
     {
         Tag.writeNamedTag(tag, dataOutput);
diff --git a/util/nbt/src/main/java/com/mojang/nbt/UnknownTagException.java b/util/nbt/src/main/java/com/mojang/nbt/UnknownTagException.java
new file mode 100644
index 000000000..f28337c04
--- /dev/null
+++ b/util/nbt/src/main/java/com/mojang/nbt/UnknownTagException.java
@@ -0,0 +1,13 @@
+package com.mojang.nbt;
+
+import java.io.IOException;
+
+public class UnknownTagException extends IOException {
+    public UnknownTagException() {
+        super();
+    }
+
+    public UnknownTagException(String message) {
+        super(message);
+    }
+}
diff --git a/game/core/src/main/java/com/mojang/nbt/ByteArrayTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/ByteArrayTag.java
similarity index 62%
rename from game/core/src/main/java/com/mojang/nbt/ByteArrayTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/ByteArrayTag.java
index 1e2bf7539..b399301c5 100644
--- a/game/core/src/main/java/com/mojang/nbt/ByteArrayTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/ByteArrayTag.java
@@ -1,13 +1,16 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
+import java.util.Arrays;
 
-public class ByteArrayTag extends Tag<byte[]>
+public class ByteArrayTag extends Tag<byte @NotNull []>
 {
 
     public ByteArrayTag()
     {
-        setValue(new byte[0]);
+        this(new byte[0]);
     }
 
     public ByteArrayTag(byte[] array)
@@ -16,7 +19,7 @@ public class ByteArrayTag extends Tag<byte[]>
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeInt(getValue().length);
@@ -24,7 +27,7 @@ public class ByteArrayTag extends Tag<byte[]>
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         int length = dis.readInt();
@@ -35,7 +38,7 @@ public class ByteArrayTag extends Tag<byte[]>
     @Override
     public byte getId()
     {
-        return 7;
+        return TAG_BYTE_ARRAY;
     }
 
     @Override
@@ -57,4 +60,13 @@ public class ByteArrayTag extends Tag<byte[]>
             return sb.toString();
         }
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(!(obj instanceof ByteArrayTag)) return false;
+        ByteArrayTag otherTag = (ByteArrayTag) obj;
+        byte[] thisData = getValue();
+        byte[] otherData = otherTag.getValue();
+        return Arrays.equals(thisData, otherData);
+    }
 }
diff --git a/game/core/src/main/java/com/mojang/nbt/ByteTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/ByteTag.java
similarity index 65%
rename from game/core/src/main/java/com/mojang/nbt/ByteTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/ByteTag.java
index 02322b783..1e7c306af 100644
--- a/game/core/src/main/java/com/mojang/nbt/ByteTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/ByteTag.java
@@ -1,12 +1,15 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 
-public class ByteTag extends Tag<Byte>
+public class ByteTag extends Tag<@NotNull Byte>
 {
 
     public ByteTag()
     {
+        this((byte) 0);
     }
 
     public ByteTag(byte value)
@@ -15,14 +18,14 @@ public class ByteTag extends Tag<Byte>
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeByte(getValue());
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         setValue(dis.readByte());
@@ -31,7 +34,7 @@ public class ByteTag extends Tag<Byte>
     @Override
     public byte getId()
     {
-        return 1;
+        return TAG_BYTE;
     }
 
     @Override
diff --git a/game/core/src/main/java/com/mojang/nbt/CompoundTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/CompoundTag.java
similarity index 83%
rename from game/core/src/main/java/com/mojang/nbt/CompoundTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/CompoundTag.java
index b7d946bd5..8a6d7938e 100644
--- a/game/core/src/main/java/com/mojang/nbt/CompoundTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/CompoundTag.java
@@ -1,9 +1,11 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 import java.util.*;
 
-public class CompoundTag extends Tag<Map<String, Tag<?>>>
+public class CompoundTag extends Tag<@NotNull Map<String, Tag<?>>>
 {
     public CompoundTag()
     {
@@ -26,12 +28,12 @@ public class CompoundTag extends Tag<Map<String, Tag<?>>>
     }
 
     @Override
-    public void write(DataOutput dos)
+    public void write(@NotNull DataOutput dos)
         throws IOException
     {
         for (Tag<?> tag : getValue().values())
         {
-            Tag.writeNamedTag(tag, dos);
+            writeNamedTag(tag, dos);
         }
 
         dos.writeByte(0);
@@ -39,13 +41,13 @@ public class CompoundTag extends Tag<Map<String, Tag<?>>>
 
 
     @Override
-    public void read(DataInput dis)
+    public void read(@NotNull DataInput dis)
         throws IOException
     {
         getValue().clear();
 
         Tag<?> tag;
-        while ((tag = Tag.readNamedTag(dis)).getId() != 0)
+        while ((tag = readNamedTag(dis)).getId() != 0)
         {
             getValue().put(tag.getTagName(), tag);
         }
@@ -64,7 +66,7 @@ public class CompoundTag extends Tag<Map<String, Tag<?>>>
     @Override
     public byte getId()
     {
-        return 10;
+        return TAG_COMPOUND;
     }
 
     public Tag<?> getTagOrDefault(final String key, Tag<?> defaultTag)
@@ -307,6 +309,27 @@ public class CompoundTag extends Tag<Map<String, Tag<?>>>
         put(key, new DoubleArrayTag(array));
     }
 
+    public long[] getLongArray(String key)
+    {
+        return getLongArrayOrDefault(key, new long[0]);
+    }
+
+    public long[] getLongArrayOrDefault(String key, long[] defaultArray)
+    {
+        Tag<?> tag = getTagOrDefault(key, null);
+
+        if (!(tag instanceof LongArrayTag))
+        {
+            return defaultArray;
+        }
+        else return ((LongArrayTag)tag).getValue();
+    }
+
+    public void putLongArray(String key, long[] array)
+    {
+        put(key, new LongArrayTag(array));
+    }
+
     public CompoundTag getCompound(String key)
     {
         return getCompoundOrDefault(key, new CompoundTag());
@@ -368,18 +391,31 @@ public class CompoundTag extends Tag<Map<String, Tag<?>>>
         Map<String, Tag<?>> data1 = this.getValue();
         Map<String, Tag<?>> data2 = ((CompoundTag)o).getValue();
 
-        if(data1.size() != data2.size()) return false;
+        if(data1.size() != data2.size()) {
+//            System.out.println("wrong sizes " + data1.size() + " " + data2.size());
+            return false;
+        }
 
         for(String key : data1.keySet()) {
             Tag<?> value1 = this.getTag(key);
             Tag<?> value2 = ((CompoundTag)o).getTag(key);
 
             if (value1 == null || value2 == null) {
-                if (value1 != value2) return false;
+                if (value1 != value2) {
+//                    System.out.println("Nulls don't match: " + key);
+                    return false;
+                }
                 continue;
             }
 
-            if(!value1.getValue().equals(value2.getValue())) {
+            if(!value1.equals(value2)) {
+//                System.out.println("Values don't equal: " + key);
+//                System.out.println();
+//                System.out.println(value1.getClass());
+//                System.out.println(value1.getValue());
+//                System.out.println();
+//                System.out.println(value2.getClass());
+//                System.out.println(value2.getValue());
                 return false;
             }
         }
diff --git a/game/core/src/main/java/com/mojang/nbt/DoubleArrayTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/DoubleArrayTag.java
similarity index 62%
rename from game/core/src/main/java/com/mojang/nbt/DoubleArrayTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/DoubleArrayTag.java
index e128c9410..afc2b2f3c 100644
--- a/game/core/src/main/java/com/mojang/nbt/DoubleArrayTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/DoubleArrayTag.java
@@ -1,15 +1,18 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.util.Arrays;
 
-public class DoubleArrayTag extends Tag<double[]>
+public class DoubleArrayTag extends Tag<double @NotNull []>
 {
 
     public DoubleArrayTag()
     {
-        setValue(new double[0]);
+        this(new double[0]);
     }
 
     public DoubleArrayTag(double[] array)
@@ -18,22 +21,22 @@ public class DoubleArrayTag extends Tag<double[]>
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeInt(getValue().length);
-        byte[] bytes = new byte[getValue().length * 8];
+        byte[] bytes = new byte[getValue().length * Double.BYTES];
         ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer().put(getValue());
         dos.write(bytes);
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         int length = dis.readInt();
         setValue(new double[length]);
-        byte[] bytes = new byte[length * 8];
+        byte[] bytes = new byte[length * Double.BYTES];
         dis.readFully(bytes);
         ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer().get(getValue());
     }
@@ -41,7 +44,7 @@ public class DoubleArrayTag extends Tag<double[]>
     @Override
     public byte getId()
     {
-        return 12;
+        return TAG_DOUBLE_ARRAY;
     }
 
     @Override
@@ -63,4 +66,13 @@ public class DoubleArrayTag extends Tag<double[]>
             return sb.toString();
         }
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(!(obj instanceof DoubleArrayTag)) return false;
+        DoubleArrayTag otherTag = (DoubleArrayTag) obj;
+        double[] thisData = getValue();
+        double[] otherData = otherTag.getValue();
+        return Arrays.equals(thisData, otherData);
+    }
 }
diff --git a/game/core/src/main/java/com/mojang/nbt/DoubleTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/DoubleTag.java
similarity index 65%
rename from game/core/src/main/java/com/mojang/nbt/DoubleTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/DoubleTag.java
index f7f97caf0..890c87c3d 100644
--- a/game/core/src/main/java/com/mojang/nbt/DoubleTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/DoubleTag.java
@@ -1,12 +1,15 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 
-public class DoubleTag extends Tag<Double>
+public class DoubleTag extends Tag<@NotNull Double>
 {
 
     public DoubleTag()
     {
+        this(0);
     }
 
     public DoubleTag(double value)
@@ -15,14 +18,14 @@ public class DoubleTag extends Tag<Double>
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeDouble(getValue());
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         setValue(dis.readDouble());
@@ -31,7 +34,7 @@ public class DoubleTag extends Tag<Double>
     @Override
     public byte getId()
     {
-        return 6;
+        return TAG_DOUBLE;
     }
 
     @Override
diff --git a/game/core/src/main/java/com/mojang/nbt/EndTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/EndTag.java
similarity index 67%
rename from game/core/src/main/java/com/mojang/nbt/EndTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/EndTag.java
index bd7d3b694..c83e0a9ee 100644
--- a/game/core/src/main/java/com/mojang/nbt/EndTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/EndTag.java
@@ -1,4 +1,6 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 
@@ -10,13 +12,13 @@ public class EndTag extends Tag<Void>
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
     }
@@ -24,7 +26,7 @@ public class EndTag extends Tag<Void>
     @Override
     public byte getId()
     {
-        return 0;
+        return TAG_END;
     }
 
     @Override
diff --git a/game/core/src/main/java/com/mojang/nbt/FloatTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/FloatTag.java
similarity index 65%
rename from game/core/src/main/java/com/mojang/nbt/FloatTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/FloatTag.java
index 2ebef7a19..8266f004a 100644
--- a/game/core/src/main/java/com/mojang/nbt/FloatTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/FloatTag.java
@@ -1,12 +1,15 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 
-public class FloatTag extends Tag<Float>
+public class FloatTag extends Tag<@NotNull Float>
 {
 
     public FloatTag()
     {
+        this(0);
     }
 
     public FloatTag(float value)
@@ -15,14 +18,14 @@ public class FloatTag extends Tag<Float>
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeFloat(getValue());
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         setValue(dis.readFloat());
@@ -31,7 +34,7 @@ public class FloatTag extends Tag<Float>
     @Override
     public byte getId()
     {
-        return 5;
+        return TAG_FLOAT;
     }
 
     @Override
diff --git a/game/core/src/main/java/com/mojang/nbt/IntTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/IntTag.java
similarity index 65%
rename from game/core/src/main/java/com/mojang/nbt/IntTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/IntTag.java
index a640383b8..03c94a1b6 100644
--- a/game/core/src/main/java/com/mojang/nbt/IntTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/IntTag.java
@@ -1,12 +1,15 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 
-public class IntTag extends Tag<Integer>
+public class IntTag extends Tag<@NotNull Integer>
 {
 
     public IntTag()
     {
+        this(0);
     }
 
     public IntTag(int value)
@@ -15,14 +18,14 @@ public class IntTag extends Tag<Integer>
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeInt(getValue());
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         setValue(dis.readInt());
@@ -31,7 +34,7 @@ public class IntTag extends Tag<Integer>
     @Override
     public byte getId()
     {
-        return 3;
+        return TAG_INT;
     }
 
     @Override
diff --git a/game/core/src/main/java/com/mojang/nbt/ListTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/ListTag.java
similarity index 75%
rename from game/core/src/main/java/com/mojang/nbt/ListTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/ListTag.java
index 9f3b10cf5..b769ac4aa 100644
--- a/game/core/src/main/java/com/mojang/nbt/ListTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/ListTag.java
@@ -1,4 +1,7 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import com.mojang.nbt.UnknownTagException;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 import java.util.ArrayList;
@@ -6,13 +9,14 @@ import java.util.Iterator;
 import java.util.List;
 
 public class ListTag
-    extends Tag<List<Tag<?>>>
+    extends Tag<@NotNull List<Tag<?>>>
     implements Iterable<Tag<?>>
 {
+    private byte tagType;
 
     public ListTag()
     {
-        setValue(new ArrayList<>());
+        this(new ArrayList<>());
     }
 
     public ListTag(List<Tag<?>> array)
@@ -21,10 +25,10 @@ public class ListTag
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
-        if(getValue().size() > 0)
+        if(!getValue().isEmpty())
         {
             tagType = getValue().get(0).getId();
         } else
@@ -41,7 +45,7 @@ public class ListTag
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         tagType = dis.readByte();
@@ -51,20 +55,20 @@ public class ListTag
 
         for(int i = 0; i < length; i++)
         {
-            Tag<?> tag = Tag.newTag(tagType);
-            if (tag != null)
-            {
+            try {
+                Tag<?> tag = newTag(tagType);
                 tag.read(dis);
                 getValue().add(tag);
+            } catch (IllegalArgumentException illegalArgumentException) {
+                throw new UnknownTagException("Unknown tag type '" + tagType + "'!");
             }
         }
-
     }
 
     @Override
     public byte getId()
     {
-        return 9;
+        return TAG_LIST;
     }
 
     @Override
@@ -103,10 +107,8 @@ public class ListTag
         return getValue().size();
     }
 
-    private byte tagType;
-
     @Override
-    public Iterator<Tag<?>> iterator()
+    public @NotNull Iterator<Tag<?>> iterator()
     {
         return getValue().iterator();
     }
diff --git a/util/nbt/src/main/java/com/mojang/nbt/tags/LongArrayTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/LongArrayTag.java
new file mode 100644
index 000000000..8170d973b
--- /dev/null
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/LongArrayTag.java
@@ -0,0 +1,77 @@
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+public class LongArrayTag extends Tag<long @NotNull []>{
+    public LongArrayTag()
+    {
+        this(new long[0]);
+    }
+
+    public LongArrayTag(long[] array)
+    {
+        super(array);
+    }
+    @Override
+    void write(@NotNull DataOutput dos)
+        throws IOException
+    {
+        dos.writeInt(getValue().length);
+        byte[] bytes = new byte[getValue().length * Long.BYTES];
+        ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(getValue());
+        dos.write(bytes);
+
+    }
+
+    @Override
+    void read(@NotNull DataInput dis)
+        throws IOException
+    {
+        int length = dis.readInt();
+        setValue(new long[length]);
+        byte[] bytes = new byte[length * Long.BYTES];
+        dis.readFully(bytes);
+        ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().get(getValue());
+    }
+
+    @Override
+    public byte getId() {
+        return TAG_LONG_ARRAY;
+    }
+
+    @Override
+    public String toString()
+    {
+        if (getValue().length > 16)
+        {
+            return "\"" + getTagName() + "\": [ " + getValue().length + " longs ]";
+        }
+        else
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append("\"").append(getTagName()).append("\": [ ");
+            for (long l : getValue())
+            {
+                sb.append(l).append(", ");
+            }
+            sb.append("]");
+            return sb.toString();
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(!(obj instanceof LongArrayTag)) return false;
+        LongArrayTag otherTag = (LongArrayTag) obj;
+        long[] thisData = getValue();
+        long[] otherData = otherTag.getValue();
+        return Arrays.equals(thisData, otherData);
+    }
+}
diff --git a/game/core/src/main/java/com/mojang/nbt/LongTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/LongTag.java
similarity index 66%
rename from game/core/src/main/java/com/mojang/nbt/LongTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/LongTag.java
index 61b285a2d..2dd4bc1f7 100644
--- a/game/core/src/main/java/com/mojang/nbt/LongTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/LongTag.java
@@ -1,12 +1,15 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 
-public class LongTag extends Tag<Long>
+public class LongTag extends Tag<@NotNull Long>
 {
 
     public LongTag()
     {
+        this(0);
     }
 
     public LongTag(long value)
@@ -15,14 +18,14 @@ public class LongTag extends Tag<Long>
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeLong(getValue());
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         setValue(dis.readLong());
@@ -31,7 +34,7 @@ public class LongTag extends Tag<Long>
     @Override
     public byte getId()
     {
-        return 4;
+        return TAG_LONG;
     }
 
     @Override
diff --git a/game/core/src/main/java/com/mojang/nbt/ShortArrayTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/ShortArrayTag.java
similarity index 62%
rename from game/core/src/main/java/com/mojang/nbt/ShortArrayTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/ShortArrayTag.java
index 645ce4670..fb202da64 100644
--- a/game/core/src/main/java/com/mojang/nbt/ShortArrayTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/ShortArrayTag.java
@@ -1,15 +1,18 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.util.Arrays;
 
-public class ShortArrayTag extends Tag<short[]>
+public class ShortArrayTag extends Tag<short @NotNull []>
 {
 
     public ShortArrayTag()
     {
-        setValue(new short[0]);
+        this(new short[0]);
     }
 
     public ShortArrayTag(short[] array)
@@ -18,23 +21,23 @@ public class ShortArrayTag extends Tag<short[]>
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeInt(getValue().length);
-        byte[] bytes = new byte[getValue().length * 2];
+        byte[] bytes = new byte[getValue().length * Short.BYTES];
         ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(getValue());
         dos.write(bytes);
 
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         int length = dis.readInt();
         setValue(new short[length]);
-        byte[] bytes = new byte[length * 2];
+        byte[] bytes = new byte[length * Short.BYTES];
         dis.readFully(bytes);
         ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(getValue());
     }
@@ -42,7 +45,7 @@ public class ShortArrayTag extends Tag<short[]>
     @Override
     public byte getId()
     {
-        return 11;
+        return TAG_SHORT_ARRAY;
     }
 
     @Override
@@ -64,4 +67,13 @@ public class ShortArrayTag extends Tag<short[]>
             return sb.toString();
         }
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(!(obj instanceof ShortArrayTag)) return false;
+        ShortArrayTag otherTag = (ShortArrayTag) obj;
+        short[] thisData = getValue();
+        short[] otherData = otherTag.getValue();
+        return Arrays.equals(thisData, otherData);
+    }
 }
diff --git a/game/core/src/main/java/com/mojang/nbt/ShortTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/ShortTag.java
similarity index 65%
rename from game/core/src/main/java/com/mojang/nbt/ShortTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/ShortTag.java
index 41544d710..6a1d17782 100644
--- a/game/core/src/main/java/com/mojang/nbt/ShortTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/ShortTag.java
@@ -1,13 +1,15 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 
-public class ShortTag extends Tag<Short>
+public class ShortTag extends Tag<@NotNull Short>
 {
 
     public ShortTag()
     {
-        super();
+        this((short) 0);
     }
 
     public ShortTag(short value)
@@ -16,14 +18,14 @@ public class ShortTag extends Tag<Short>
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeShort(getValue());
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         setValue(dis.readShort());
@@ -32,7 +34,7 @@ public class ShortTag extends Tag<Short>
     @Override
     public byte getId()
     {
-        return 2;
+        return TAG_SHORT;
     }
 
     @Override
diff --git a/game/core/src/main/java/com/mojang/nbt/StringTag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/StringTag.java
similarity index 51%
rename from game/core/src/main/java/com/mojang/nbt/StringTag.java
rename to util/nbt/src/main/java/com/mojang/nbt/tags/StringTag.java
index 172d2944e..2972ac776 100644
--- a/game/core/src/main/java/com/mojang/nbt/StringTag.java
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/StringTag.java
@@ -1,33 +1,31 @@
-package com.mojang.nbt;
+package com.mojang.nbt.tags;
+
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
+import java.util.Objects;
 
-public class StringTag extends Tag<String>
+public class StringTag extends Tag<@NotNull String>
 {
 
     public StringTag()
     {
-        setValue("");
+        this("");
     }
 
-    public StringTag(String value)
-    {
-        super(value);
-        if(value == null)
-        {
-            throw new IllegalArgumentException("Empty string not allowed");
-        }
+    public StringTag(@NotNull String value) {
+        super(Objects.requireNonNull(value, "Null string not allowed!"));
     }
 
     @Override
-    void write(DataOutput dos)
+    void write(@NotNull DataOutput dos)
         throws IOException
     {
         dos.writeUTF(getValue());
     }
 
     @Override
-    void read(DataInput dis)
+    void read(@NotNull DataInput dis)
         throws IOException
     {
         setValue(dis.readUTF());
@@ -36,7 +34,7 @@ public class StringTag extends Tag<String>
     @Override
     public byte getId()
     {
-        return 8;
+        return TAG_STRING;
     }
 
     @Override
diff --git a/util/nbt/src/main/java/com/mojang/nbt/tags/Tag.java b/util/nbt/src/main/java/com/mojang/nbt/tags/Tag.java
new file mode 100644
index 000000000..cb2918cfc
--- /dev/null
+++ b/util/nbt/src/main/java/com/mojang/nbt/tags/Tag.java
@@ -0,0 +1,279 @@
+package com.mojang.nbt.tags;
+
+import com.mojang.nbt.UnknownTagException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.*;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public abstract class Tag<T>
+{
+    static final int TAG_END = 0;
+    static final int TAG_BYTE = 1;
+    static final int TAG_SHORT = 2;
+    static final int TAG_INT = 3;
+    static final int TAG_LONG = 4;
+    static final int TAG_FLOAT = 5;
+    static final int TAG_DOUBLE = 6;
+    static final int TAG_BYTE_ARRAY = 7;
+    static final int TAG_STRING = 8;
+    static final int TAG_LIST = 9;
+    static final int TAG_COMPOUND = 10;
+    static final int TAG_SHORT_ARRAY = 11;
+    static final int TAG_DOUBLE_ARRAY = 12;
+    static final int TAG_LONG_ARRAY = 13;
+
+    /**
+     * The key of the tag.
+     */
+    private @Nullable String name = null;
+    /**
+     * The value of the tag.
+     */
+    private T value;
+
+    public Tag() { }
+
+    public Tag(T value)
+    {
+        this.value = value;
+    }
+
+    /**
+     * Reads the contents of the tag from the input stream.
+     * @param dis The stream to read the tag data from.
+     * @throws IOException Thrown if reading from the stream failed.
+     */
+    abstract void read(@NotNull DataInput dis)
+        throws IOException;
+
+    /**
+     * Writes the contents of the tag to the output stream.
+     * @param dos The stream to write the tag data to.
+     * @throws IOException Thrown if writing to the stream failed.
+     */
+    abstract void write(@NotNull DataOutput dos)
+        throws IOException;
+
+    /**
+     * Fetches the ID of the tag's type.
+     * @return The ID of the tag's type.
+     */
+    public abstract byte getId();
+
+    /**
+     * Fetches the tag's name.
+     * @return The tag's name.
+     */
+    public @NotNull String getTagName()
+    {
+        return name == null ? "" : name;
+    }
+
+    /**
+     * Sets the tag's key.
+     * @param key The new key of the tag.
+     * @return The tag that had its key set.
+     */
+    public @NotNull Tag<T> setName(String key)
+    {
+        this.name = key;
+        return this;
+    }
+
+    /**
+     * Fetches the tag's value.
+     * @return The tag's value.
+     */
+    public T getValue()
+    {
+        return value;
+    }
+
+    /**
+     * Sets the tag's value.
+     * @param value The new value of the tag.
+     * @return The tag that had its value set.
+     */
+    public @NotNull Tag<T> setValue(T value)
+    {
+        this.value = value;
+        return this;
+    }
+
+    /**
+     * Reads a tag from the input stream.
+     * @param dis The stream to read a tag from.
+     * @return The tag read from the stream.
+     * @throws IOException Thrown if reading from the stream failed.
+     */
+    @SuppressWarnings("unused")
+    public static Tag<?> readNamedTag(@NotNull DataInput dis)
+        throws IOException
+    {
+        byte typeId = dis.readByte();
+
+        if(typeId == TAG_END) {
+            return new EndTag();
+        }
+        try {
+            Tag<?> tag = newTag(typeId);
+            tag.name = dis.readUTF();
+            tag.read(dis);
+            return tag;
+        } catch (IllegalArgumentException illegalArgumentException) {
+            throw new UnknownTagException("Unknown tag type '" + typeId + "'!");
+        }
+    }
+
+    /**
+     * Writes a tag to the output stream.
+     * @param tag The tag to write to the stream.
+     * @param dos The stream to write to.
+     * @throws IOException Thrown if writing to the stream failed.
+     */
+    @SuppressWarnings("unused")
+    public static void writeNamedTag(@NotNull Tag<?> tag, @NotNull DataOutput dos)
+        throws IOException
+    {
+        dos.writeByte(tag.getId());
+        if(tag.getId() != TAG_END)
+        {
+            dos.writeUTF(tag.getTagName());
+            tag.write(dos);
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(!(obj instanceof Tag<?>)) return false;
+        Tag<?> tag = (Tag<?>) obj;
+        return Objects.equals(getValue(), tag.getValue());
+    }
+
+    /**
+     * Creates a new tag wrapping the specified type.
+     * @param type The type to wrap.
+     * @return The wrapped type, or null if no such wrapper exists or is possible.
+     */
+    @SuppressWarnings({"unchecked", "unused"})
+    public static @NotNull <T> Tag<T> createTagOfType(@NotNull Class<T> type)
+    {
+        if (type.isArray()) {
+            Class<?> arrayType = type.getComponentType();
+            if (arrayType == Byte.class || arrayType == byte.class) {
+                return (Tag<T>) new ByteArrayTag();
+            } else if (arrayType == Short.class || arrayType == short.class) {
+                return (Tag<T>) new ShortArrayTag();
+            } else if (arrayType == Long.class || arrayType == long.class) {
+                return (Tag<T>) new LongArrayTag();
+            } else if (arrayType == Double.class || arrayType == double.class) {
+                return (Tag<T>) new DoubleArrayTag();
+            }
+            throw new IllegalArgumentException("No NBT Tag type for array of '" + arrayType + "'!");
+        } else if (type == Byte.class || type == byte.class) {
+            return (Tag<T>) new ByteTag();
+        } else if (type == Short.class || type == short.class) {
+            return (Tag<T>) new ShortTag();
+        } else if (type == Integer.class || type == int.class) {
+            return (Tag<T>) new IntTag();
+        } else if (type == Long.class || type == long.class) {
+            return (Tag<T>) new LongTag();
+        } else if (type == Float.class || type == float.class) {
+            return (Tag<T>) new FloatTag();
+        } else if (type == Double.class || type == double.class) {
+            return (Tag<T>) new DoubleTag();
+        } else if (type == String.class) {
+            return (Tag<T>) new StringTag();
+        } else if (List.class.isAssignableFrom(type)) {
+            return (Tag<T>) new ListTag();
+        } else if (Map.class.isAssignableFrom(type)) {
+            return (Tag<T>) new CompoundTag();
+        }
+        throw new IllegalArgumentException("No NBT Tag type for type '" + type + "'!");
+    }
+
+    /**
+     * Creates a tag according to the given type ID.
+     * @param type The ID of the type of tag to create.
+     * @return The created tag, or null if the type ID doesn't match any tag types.
+     */
+    @SuppressWarnings("unused")
+    public static @NotNull Tag<?> newTag(byte type) {
+        switch (type) {
+            case TAG_END:
+                return new EndTag();
+            case TAG_BYTE:
+                return new ByteTag();
+            case TAG_SHORT:
+                return new ShortTag();
+            case TAG_INT:
+                return new IntTag();
+            case TAG_LONG:
+                return new LongTag();
+            case TAG_FLOAT:
+                return new FloatTag();
+            case TAG_DOUBLE:
+                return new DoubleTag();
+            case TAG_BYTE_ARRAY:
+                return new ByteArrayTag();
+            case TAG_STRING:
+                return new StringTag();
+            case TAG_LIST:
+                return new ListTag();
+            case TAG_COMPOUND:
+                return new CompoundTag();
+            case TAG_SHORT_ARRAY:
+                return new ShortArrayTag();
+            case TAG_DOUBLE_ARRAY:
+                return new DoubleArrayTag();
+            case TAG_LONG_ARRAY:
+                return new LongArrayTag();
+        }
+        throw new IllegalArgumentException("No NBT Tag type for type '" + type + "'!");
+    }
+
+    /**
+     * Gets a string representing a tag's type.
+     * @param type The type ID corresponding to the type of tag.
+     * @return A string representing the tag type ID.
+     */
+    @SuppressWarnings("unused")
+    public static @NotNull String getTagName(byte type)
+    {
+        switch (type) {
+            case TAG_END:
+                return "TAG_End";
+            case TAG_BYTE:
+                return "TAG_Byte";
+            case TAG_SHORT:
+                return "TAG_Short";
+            case TAG_INT:
+                return "TAG_Int";
+            case TAG_LONG:
+                return "TAG_Long";
+            case TAG_FLOAT:
+                return "TAG_Float";
+            case TAG_DOUBLE:
+                return "TAG_Double";
+            case TAG_BYTE_ARRAY:
+                return "TAG_Byte_Array";
+            case TAG_STRING:
+                return "TAG_String";
+            case TAG_LIST:
+                return "TAG_List";
+            case TAG_COMPOUND:
+                return "TAG_Compound";
+            case TAG_SHORT_ARRAY:
+                return "TAG_Short_Array";
+            case TAG_DOUBLE_ARRAY:
+                return "TAG_Double_Array";
+            case TAG_LONG_ARRAY:
+                return "TAG_Long_Array";
+        }
+        throw new IllegalArgumentException("No NBT Tag type for type '" + type + "'!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestByteArrayTag.java b/util/nbt/src/test/java/TestByteArrayTag.java
new file mode 100644
index 000000000..704652bc9
--- /dev/null
+++ b/util/nbt/src/test/java/TestByteArrayTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.ByteArrayTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestByteArrayTag {
+    @Test
+    public void testTag() {
+        ByteArrayTag byteArrayTagEmpty = new ByteArrayTag();
+        Assertions.assertEquals(byteArrayTagEmpty.getId(), 7, "Tag id does not match its expected id!");
+        Assertions.assertArrayEquals(new byte[0], byteArrayTagEmpty.getValue(), "Default byte array tag value should be and empty array!");
+
+        ByteArrayTag byteArrayTag1 = new ByteArrayTag(new byte[]{-1, 0, 2, 7, 9, Byte.MAX_VALUE, Byte.MIN_VALUE});
+        Assertions.assertArrayEquals(new byte[]{-1, 0, 2, 7, 9, Byte.MAX_VALUE, Byte.MIN_VALUE}, byteArrayTag1.getValue(), "Tag value does not match its equivalent array!");
+
+        ByteArrayTag byteArrayTag2 = new ByteArrayTag(new byte[]{-1, 0, 2, 7, 9, Byte.MAX_VALUE, Byte.MIN_VALUE});
+        Assertions.assertEquals(byteArrayTag2, byteArrayTag1, "Tag value does not equal its equivalent tag!");
+
+        ByteArrayTag byteArrayTag3 = new ByteArrayTag(new byte[]{Byte.MIN_VALUE, Byte.MAX_VALUE, 9, 7, 2, 0, -1});
+        Assertions.assertNotEquals(byteArrayTag3, byteArrayTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestByteTag.java b/util/nbt/src/test/java/TestByteTag.java
new file mode 100644
index 000000000..a37057e58
--- /dev/null
+++ b/util/nbt/src/test/java/TestByteTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.ByteTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestByteTag {
+    @Test
+    public void testTag() {
+        ByteTag byteTagEmpty = new ByteTag();
+        Assertions.assertEquals(byteTagEmpty.getId(), 1, "Tag id does not match its expected id!");
+        Assertions.assertEquals(byteTagEmpty.getValue(), (byte) 0, "Default byte tag value should be 0!");
+
+        ByteTag byteTag1 = new ByteTag(Byte.MAX_VALUE);
+        Assertions.assertEquals(Byte.MAX_VALUE, byteTag1.getValue(), "Tag value does not match its equivalent value!");
+
+        ByteTag byteTag2 = new ByteTag(Byte.MAX_VALUE);
+        Assertions.assertEquals(byteTag2, byteTag1, "Tag value does not equal its equivalent tag!");
+
+        ByteTag byteTag3 = new ByteTag(Byte.MIN_VALUE);
+        Assertions.assertNotEquals(byteTag3, byteTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestCompoundTag.java b/util/nbt/src/test/java/TestCompoundTag.java
new file mode 100644
index 000000000..f8649b196
--- /dev/null
+++ b/util/nbt/src/test/java/TestCompoundTag.java
@@ -0,0 +1,116 @@
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.IntTag;
+import com.mojang.nbt.tags.ListTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestCompoundTag {
+    @Test
+    public void testTag() {
+        CompoundTag compoundTagEmpty1 = new CompoundTag();
+        CompoundTag compoundTagEmpty2 = new CompoundTag();
+        Assertions.assertNotNull(compoundTagEmpty1.getValue(), "Empty compound tag should be non null!");
+        Assertions.assertTrue(compoundTagEmpty1.getValue().isEmpty(), "Empty compound tag should be empty!");
+        Assertions.assertEquals(compoundTagEmpty1.getId(), 10, "Tag id does not match its expected id!");
+        Assertions.assertEquals(compoundTagEmpty1, compoundTagEmpty2, "Empty tags should pass equality check!");
+
+        Assertions.assertEquals(false, compoundTagEmpty1.getBoolean("bool"), "Compound tag getBoolean does not equal expected default!");
+        Assertions.assertEquals(0, compoundTagEmpty1.getByte("byte"), "Compound tag getByte does not equal expected default!");
+        Assertions.assertArrayEquals(new byte[0], compoundTagEmpty1.getByteArray("byteArray"), "Compound tag getByteArray does not equal expected default!");
+        Assertions.assertEquals(0, compoundTagEmpty1.getShort("short"), "Compound tag getShort does not equal expected default!");
+        Assertions.assertArrayEquals(new short[0], compoundTagEmpty1.getShortArray("shortArray"), "Compound tag getShortArray does not equal expected default!");
+        Assertions.assertEquals(0, compoundTagEmpty1.getInteger("int"), "Compound tag getInteger does not equal expected default!");
+//        Assertions.assertArrayEquals(new short[0], compoundTagEmpty1.getIntegerArray("intArray"), "Compound tag getIntegerArray does not equal expected default!");
+        Assertions.assertEquals(0, compoundTagEmpty1.getFloat("float"), "Compound tag getFloat does not equal expected default!");
+//        Assertions.assertArrayEquals(new float[0], compoundTagEmpty1.getFloatArray("floatArray"), "Compound tag getFloatArray does not equal expected default!");
+        Assertions.assertEquals(0, compoundTagEmpty1.getLong("long"), "Compound tag getLong does not equal expected default!");
+        Assertions.assertArrayEquals(new long[0], compoundTagEmpty1.getLongArray("longArray"), "Compound tag getLongArray does not equal expected default!");
+        Assertions.assertEquals(0, compoundTagEmpty1.getDouble("double"), "Compound tag getDouble does not equal expected default!");
+        Assertions.assertArrayEquals(new double[0], compoundTagEmpty1.getDoubleArray("doubleArray"), "Compound tag getDoubleArray does not equal expected default!");
+        Assertions.assertEquals("", compoundTagEmpty1.getString("string"), "Compound tag getString does not equal expected default!");
+        Assertions.assertEquals(new ListTag(), compoundTagEmpty1.getList("list"), "Compound tag getList does not equal expected default!");
+        Assertions.assertEquals(new CompoundTag(), compoundTagEmpty1.getCompound("compound"), "Compound tag getCompound does not equal expected default!");
+
+        boolean defBool = true;
+        byte defByte = Byte.MAX_VALUE;
+        byte[] defByteArray = new byte[]{Byte.MIN_VALUE, 0, Byte.MAX_VALUE};
+        short defShort = Short.MAX_VALUE;
+        short[] defShortArray = new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE};
+        int defInt = Integer.MAX_VALUE;
+        int[] defIntArray = new int[]{Integer.MIN_VALUE, 0, Integer.MAX_VALUE};
+        float defFloat = Float.MAX_VALUE;
+        float[] defFloatArray = new float[]{Float.NEGATIVE_INFINITY, Float.MIN_VALUE, Float.NaN, 0, Float.MAX_VALUE, Float.POSITIVE_INFINITY};
+        long defLong = Long.MAX_VALUE;
+        long[] defLongArray = new long[]{Long.MIN_VALUE, 0, Long.MAX_VALUE};
+        double defDouble = Double.MAX_VALUE;
+        double[] defDoubleArray = new double[]{Double.NEGATIVE_INFINITY, Double.MIN_VALUE, Double.NaN, 0, Double.MAX_VALUE, Double.POSITIVE_INFINITY};
+        String defString = "default";
+        ListTag defList = new ListTag(); defList.addTag(new IntTag(0)); defList.addTag(new IntTag(1)); defList.addTag(new IntTag(2));
+        CompoundTag defCompound = new CompoundTag(); defCompound.putInt("0", 0); defCompound.putLong("0", 0);
+
+        Assertions.assertEquals(defBool, compoundTagEmpty1.getBooleanOrDefault("bool", defBool), "Compound tag getBooleanOrDefault does not equal expected default!");
+        Assertions.assertEquals(defByte, compoundTagEmpty1.getByteOrDefault("byte", defByte), "Compound tag getByteOrDefault does not equal expected default!");
+        Assertions.assertArrayEquals(defByteArray, compoundTagEmpty1.getByteArrayOrDefault("byteArray", defByteArray), "Compound tag getByteArrayOrDefault does not equal expected default!");
+        Assertions.assertEquals(defShort, compoundTagEmpty1.getShortOrDefault("short", defShort), "Compound tag getShortOrDefault does not equal expected default!");
+        Assertions.assertArrayEquals(defShortArray, compoundTagEmpty1.getShortArrayOrDefault("shortArray", defShortArray), "Compound tag getShortArrayOrDefault does not equal expected default!");
+        Assertions.assertEquals(defInt, compoundTagEmpty1.getIntegerOrDefault("int", defInt), "Compound tag getIntegerOrDefault does not equal expected default!");
+//        Assertions.assertArrayEquals(defShortArray, compoundTagEmpty1.getIntegerArrayOrDefault("intArray", defShortArray), "Compound tag getIntegerArrayOrDefault does not equal expected default!");
+        Assertions.assertEquals(defFloat, compoundTagEmpty1.getFloatOrDefault("float", defFloat), "Compound tag getFloatOrDefault does not equal expected default!");
+//        Assertions.assertArrayEquals(defFloatArray, compoundTagEmpty1.getFloatArrayOrDefault("floatArray", defFloatArray), "Compound tag getFloatArrayOrDefault does not equal expected default!");
+        Assertions.assertEquals(defLong, compoundTagEmpty1.getLongOrDefault("long", defLong), "Compound tag getLongOrDefault does not equal expected default!");
+        Assertions.assertArrayEquals(defLongArray, compoundTagEmpty1.getLongArrayOrDefault("longArray", defLongArray), "Compound tag getLongArrayOrDefault does not equal expected default!");
+        Assertions.assertEquals(defDouble, compoundTagEmpty1.getDoubleOrDefault("double", defDouble), "Compound tag getDoubleOrDefault does not equal expected default!");
+        Assertions.assertArrayEquals(defDoubleArray, compoundTagEmpty1.getDoubleArrayOrDefault("doubleArray", defDoubleArray), "Compound tag getDoubleArrayOrDefault does not equal expected default!");
+        Assertions.assertEquals(defString, compoundTagEmpty1.getStringOrDefault("string", defString), "Compound tag getStringOrDefault does not equal expected default!");
+        Assertions.assertEquals(defList, compoundTagEmpty1.getListOrDefault("list", defList), "Compound tag getListOrDefault does not equal expected default!");
+        Assertions.assertEquals(defCompound, compoundTagEmpty1.getCompoundOrDefault("compound", defCompound), "Compound tag getCompoundOrDefault does not equal expected default!");
+
+        CompoundTag basicCompoundTag = new CompoundTag();
+        basicCompoundTag.putString("String", "Hello World!");
+        basicCompoundTag.putInt("Int", 7695);
+        basicCompoundTag.putByteArray("ByteArray", new byte[]{Byte.MIN_VALUE, 0, Byte.MAX_VALUE});
+
+        Assertions.assertEquals(3, basicCompoundTag.getValue().size(), "Compound tag size does not match the expected number of entries");
+        Assertions.assertEquals("Hello World!", basicCompoundTag.getString("String"));
+        Assertions.assertEquals(7695, basicCompoundTag.getInteger("Int"));
+        Assertions.assertArrayEquals(new byte[]{Byte.MIN_VALUE, 0, Byte.MAX_VALUE}, basicCompoundTag.getByteArray("ByteArray"));
+
+        CompoundTag allTags = new CompoundTag();
+
+        allTags.putBoolean("bool", defBool);
+        allTags.putByte("byte", defByte);
+        allTags.putByteArray("byteArray", defByteArray);
+        allTags.putShort("short", defShort);
+        allTags.putShortArray("shortArray", defShortArray);
+        allTags.putInt("int", defInt);
+//        allTags.putIntegerArray("intArray", defIntArray);
+        allTags.putFloat("float", defFloat);
+//        allTags.putFloatArray("floatArray", defFloatArray);
+        allTags.putLong("long", defLong);
+        allTags.putLongArray("longArray", defLongArray);
+        allTags.putDouble("double", defDouble);
+        allTags.putDoubleArray("doubleArray", defDoubleArray);
+        allTags.putString("string", defString);
+        allTags.putList("list", defList);
+        allTags.putCompound("compound", defCompound);
+
+        Assertions.assertEquals(defBool, allTags.getBoolean("bool"), "Compound tag getBoolean does not equal expected default!");
+        Assertions.assertEquals(defByte, allTags.getByte("byte"), "Compound tag getByte does not equal expected default!");
+        Assertions.assertArrayEquals(defByteArray, allTags.getByteArray("byteArray"), "Compound tag getByteArray does not equal expected default!");
+        Assertions.assertEquals(defShort, allTags.getShort("short"), "Compound tag getShort does not equal expected default!");
+        Assertions.assertArrayEquals(defShortArray, allTags.getShortArray("shortArray"), "Compound tag getShortArray does not equal expected default!");
+        Assertions.assertEquals(defInt, allTags.getInteger("int"), "Compound tag getInteger does not equal expected default!");
+//        Assertions.assertArrayEquals(defIntArray, allTags.getIntegerArray("intArray"), "Compound tag getIntegerArray does not equal expected default!");
+        Assertions.assertEquals(defFloat, allTags.getFloat("float"), "Compound tag getFloat does not equal expected default!");
+//        Assertions.assertArrayEquals(defFloatArray, allTags.getFloatArray("floatArray"), "Compound tag getFloatArray does not equal expected default!");
+        Assertions.assertEquals(defLong, allTags.getLong("long"), "Compound tag getLong does not equal expected default!");
+        Assertions.assertArrayEquals(defLongArray, allTags.getLongArray("longArray"), "Compound tag getLongArray does not equal expected default!");
+        Assertions.assertEquals(defDouble, allTags.getDouble("double"), "Compound tag getDouble does not equal expected default!");
+        Assertions.assertArrayEquals(defDoubleArray, allTags.getDoubleArray("doubleArray"), "Compound tag getDoubleArray does not equal expected default!");
+        Assertions.assertEquals(defString, allTags.getString("string"), "Compound tag getString does not equal expected default!");
+        Assertions.assertEquals(defList, allTags.getList("list"), "Compound tag getList does not equal expected default!");
+        Assertions.assertEquals(defCompound, allTags.getCompound("compound"), "Compound tag getCompound does not equal expected default!");
+
+        Assertions.assertEquals(allTags, new CompoundTag(allTags), "Compound tag clone does not equal its source!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestDoubleArrayTag.java b/util/nbt/src/test/java/TestDoubleArrayTag.java
new file mode 100644
index 000000000..3ca53d2d6
--- /dev/null
+++ b/util/nbt/src/test/java/TestDoubleArrayTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.DoubleArrayTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestDoubleArrayTag {
+    @Test
+    public void testTag() {
+        DoubleArrayTag doubleArrayTagEmpty = new DoubleArrayTag();
+        Assertions.assertEquals(doubleArrayTagEmpty.getId(), 12, "Tag id does not match its expected id!");
+        Assertions.assertArrayEquals(new double[0], doubleArrayTagEmpty.getValue(), "Default double array tag value should be and empty array!");
+
+        DoubleArrayTag doubleArrayTag1 = new DoubleArrayTag(new double[]{-1, 0, 2, 7, 9, Double.NEGATIVE_INFINITY, Double.MIN_VALUE, Double.NaN, 0, Double.MAX_VALUE, Double.POSITIVE_INFINITY});
+        Assertions.assertArrayEquals(new double[]{-1, 0, 2, 7, 9, Double.NEGATIVE_INFINITY, Double.MIN_VALUE, Double.NaN, 0, Double.MAX_VALUE, Double.POSITIVE_INFINITY}, doubleArrayTag1.getValue(), "Tag value does not match its equivalent array!");
+
+        DoubleArrayTag doubleArrayTag2 = new DoubleArrayTag(new double[]{-1, 0, 2, 7, 9, Double.NEGATIVE_INFINITY, Double.MIN_VALUE, Double.NaN, 0, Double.MAX_VALUE, Double.POSITIVE_INFINITY});
+        Assertions.assertEquals(doubleArrayTag2, doubleArrayTag1, "Tag value does not equal its equivalent tag!");
+
+        DoubleArrayTag doubleArrayTag3 = new DoubleArrayTag(new double[]{Double.NEGATIVE_INFINITY, Double.MIN_VALUE, Double.NaN, 0, Double.MAX_VALUE, Double.POSITIVE_INFINITY, 9, 7, 2, 0, -1});
+        Assertions.assertNotEquals(doubleArrayTag3, doubleArrayTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestDoubleTag.java b/util/nbt/src/test/java/TestDoubleTag.java
new file mode 100644
index 000000000..0085385d9
--- /dev/null
+++ b/util/nbt/src/test/java/TestDoubleTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.DoubleTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestDoubleTag {
+    @Test
+    public void testTag() {
+        DoubleTag doubleTagEmpty = new DoubleTag();
+        Assertions.assertEquals(doubleTagEmpty.getId(), 6, "Tag id does not match its expected id!");
+        Assertions.assertEquals(doubleTagEmpty.getValue(), 0, "Default double tag value should be 0!");
+
+        DoubleTag doubleTag1 = new DoubleTag(Double.MAX_VALUE);
+        Assertions.assertEquals(Double.MAX_VALUE, doubleTag1.getValue(), "Tag value does not match its equivalent value!");
+
+        DoubleTag doubleTag2 = new DoubleTag(Double.MAX_VALUE);
+        Assertions.assertEquals(doubleTag2, doubleTag1, "Tag value does not equal its equivalent tag!");
+
+        DoubleTag doubleTag3 = new DoubleTag(Double.MIN_VALUE);
+        Assertions.assertNotEquals(doubleTag3, doubleTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestFloatTag.java b/util/nbt/src/test/java/TestFloatTag.java
new file mode 100644
index 000000000..79aed0b71
--- /dev/null
+++ b/util/nbt/src/test/java/TestFloatTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.FloatTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestFloatTag {
+    @Test
+    public void testTag() {
+        FloatTag floatTagEmpty = new FloatTag();
+        Assertions.assertEquals(floatTagEmpty.getId(), 5, "Tag id does not match its expected id!");
+        Assertions.assertEquals(floatTagEmpty.getValue(), 0, "Default float tag value should be 0!");
+
+        FloatTag floatTag1 = new FloatTag(Float.MAX_VALUE);
+        Assertions.assertEquals(Float.MAX_VALUE, floatTag1.getValue(), "Tag value does not match its equivalent value!");
+
+        FloatTag floatTag2 = new FloatTag(Float.MAX_VALUE);
+        Assertions.assertEquals(floatTag2, floatTag1, "Tag value does not equal its equivalent tag!");
+
+        FloatTag floatTag3 = new FloatTag(Float.MIN_VALUE);
+        Assertions.assertNotEquals(floatTag3, floatTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestIntTag.java b/util/nbt/src/test/java/TestIntTag.java
new file mode 100644
index 000000000..73442810b
--- /dev/null
+++ b/util/nbt/src/test/java/TestIntTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.IntTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestIntTag {
+    @Test
+    public void testTag() {
+        IntTag intTagEmpty = new IntTag();
+        Assertions.assertEquals(intTagEmpty.getId(), 3, "Tag id does not match its expected id!");
+        Assertions.assertEquals(intTagEmpty.getValue(), 0, "Default int tag value should be 0!");
+
+        IntTag intTag1 = new IntTag(Integer.MAX_VALUE);
+        Assertions.assertEquals(Integer.MAX_VALUE, intTag1.getValue(), "Tag value does not match its equivalent value!");
+
+        IntTag intTag2 = new IntTag(Integer.MAX_VALUE);
+        Assertions.assertEquals(intTag2, intTag1, "Tag value does not equal its equivalent tag!");
+
+        IntTag intTag3 = new IntTag(Integer.MIN_VALUE);
+        Assertions.assertNotEquals(intTag3, intTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestListTag.java b/util/nbt/src/test/java/TestListTag.java
new file mode 100644
index 000000000..0dae08faf
--- /dev/null
+++ b/util/nbt/src/test/java/TestListTag.java
@@ -0,0 +1,41 @@
+import com.mojang.nbt.tags.IntTag;
+import com.mojang.nbt.tags.ListTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestListTag {
+    @Test
+    public void testTag() {
+        ListTag listTagEmpty = new ListTag();
+        Assertions.assertEquals(listTagEmpty.getId(), 9, "Tag id does not match its expected id!");
+        Assertions.assertNotNull(listTagEmpty.getValue(), "Default list tag should not be null!");
+        Assertions.assertTrue(listTagEmpty.getValue().isEmpty(), "Default list tag should be empty!");
+
+        ListTag intTags1 = new ListTag();
+        intTags1.addTag(new IntTag(0));
+        intTags1.addTag(new IntTag(1));
+        intTags1.addTag(new IntTag(2));
+        intTags1.addTag(new IntTag(3));
+        intTags1.addTag(new IntTag(4));
+
+        Assertions.assertEquals(5, intTags1.getValue().size(), "List tag size does not match expected value!");
+
+        ListTag intTags2 = new ListTag();
+        intTags2.addTag(new IntTag(0));
+        intTags2.addTag(new IntTag(1));
+        intTags2.addTag(new IntTag(2));
+        intTags2.addTag(new IntTag(3));
+        intTags2.addTag(new IntTag(4));
+
+        Assertions.assertEquals(intTags1, intTags2, "List tag does not equal equivalent list!");
+
+        ListTag intTags3 = new ListTag();
+        intTags3.addTag(new IntTag(4));
+        intTags3.addTag(new IntTag(3));
+        intTags3.addTag(new IntTag(2));
+        intTags3.addTag(new IntTag(1));
+        intTags3.addTag(new IntTag(0));
+
+        Assertions.assertNotEquals(intTags2, intTags3, "List tag equals a non equivalent list!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestLongArrayTag.java b/util/nbt/src/test/java/TestLongArrayTag.java
new file mode 100644
index 000000000..671c0c543
--- /dev/null
+++ b/util/nbt/src/test/java/TestLongArrayTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.LongArrayTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestLongArrayTag {
+    @Test
+    public void testTag() {
+        LongArrayTag longArrayTagEmpty = new LongArrayTag();
+        Assertions.assertEquals(longArrayTagEmpty.getId(), 13, "Tag id does not match its expected id!");
+        Assertions.assertArrayEquals(new long[0], longArrayTagEmpty.getValue(), "Default long array tag value should be and empty array!");
+
+        LongArrayTag longArrayTag1 = new LongArrayTag(new long[]{-1, 0, 2, 7, 9, Long.MIN_VALUE, 0, Long.MAX_VALUE});
+        Assertions.assertArrayEquals(new long[]{-1, 0, 2, 7, 9, Long.MIN_VALUE, 0, Long.MAX_VALUE}, longArrayTag1.getValue(), "Tag value does not match its equivalent array!");
+
+        LongArrayTag longArrayTag2 = new LongArrayTag(new long[]{-1, 0, 2, 7, 9, Long.MIN_VALUE, 0, Long.MAX_VALUE});
+        Assertions.assertEquals(longArrayTag2, longArrayTag1, "Tag value does not equal its equivalent tag!");
+
+        LongArrayTag longArrayTag3 = new LongArrayTag(new long[]{Long.MIN_VALUE, 0, Long.MAX_VALUE, 9, 7, 2, 0, -1});
+        Assertions.assertNotEquals(longArrayTag3, longArrayTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestLongTag.java b/util/nbt/src/test/java/TestLongTag.java
new file mode 100644
index 000000000..3832ee0bf
--- /dev/null
+++ b/util/nbt/src/test/java/TestLongTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.LongTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestLongTag {
+    @Test
+    public void testTag() {
+        LongTag longTagEmpty = new LongTag();
+        Assertions.assertEquals(longTagEmpty.getId(), 4, "Tag id does not match its expected id!");
+        Assertions.assertEquals(longTagEmpty.getValue(), 0, "Default long tag value should be 0!");
+
+        LongTag longTag1 = new LongTag(Long.MAX_VALUE);
+        Assertions.assertEquals(Long.MAX_VALUE, longTag1.getValue(), "Tag value does not match its equivalent value!");
+
+        LongTag longTag2 = new LongTag(Long.MAX_VALUE);
+        Assertions.assertEquals(longTag2, longTag1, "Tag value does not equal its equivalent tag!");
+
+        LongTag longTag3 = new LongTag(Long.MIN_VALUE);
+        Assertions.assertNotEquals(longTag3, longTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestNbtIo.java b/util/nbt/src/test/java/TestNbtIo.java
new file mode 100644
index 000000000..3ba692855
--- /dev/null
+++ b/util/nbt/src/test/java/TestNbtIo.java
@@ -0,0 +1,306 @@
+import com.mojang.nbt.NbtIo;
+import com.mojang.nbt.tags.ByteArrayTag;
+import com.mojang.nbt.tags.ByteTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.DoubleArrayTag;
+import com.mojang.nbt.tags.DoubleTag;
+import com.mojang.nbt.tags.FloatTag;
+import com.mojang.nbt.tags.IntTag;
+import com.mojang.nbt.tags.ListTag;
+import com.mojang.nbt.tags.LongArrayTag;
+import com.mojang.nbt.tags.LongTag;
+import com.mojang.nbt.tags.ShortArrayTag;
+import com.mojang.nbt.tags.ShortTag;
+import com.mojang.nbt.tags.StringTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+public class TestNbtIo {
+    @Test
+    @DisplayName("Read Compressed Example NBT files")
+    public void readCompressedExamples() {
+        try {
+            CompoundTag exampleData = NbtIo.readCompressed(TestNbtIo.class.getResourceAsStream("/examples/compressed/helloWorld.dat"));
+            CompoundTag expected = new CompoundTag();
+            expected.putString("Hello", "World!");
+
+            Assertions.assertEquals(expected, exampleData);
+        } catch (IOException e) {
+            Assertions.fail("Failed to read compressed example tag 'helloWorld.dat'", e);
+        }
+
+        try {
+            CompoundTag exampleData = NbtIo.readCompressed(TestNbtIo.class.getResourceAsStream("/examples/compressed/allTags_1_0_0.dat"));
+            CompoundTag expected = new CompoundTag();
+            expected.put("String", new StringTag("String"));
+            expected.put("Byte", new ByteTag(Byte.MAX_VALUE));
+            expected.put("Short", new ShortTag(Short.MAX_VALUE));
+            expected.put("Int", new IntTag(Integer.MAX_VALUE));
+            expected.put("Long", new LongTag(Long.MAX_VALUE));
+            expected.put("Float", new FloatTag(Float.MAX_VALUE));
+            expected.put("Double", new DoubleTag(Double.MAX_VALUE));
+            expected.put("ByteArray", new ByteArrayTag(new byte[]{Byte.MIN_VALUE, 0, Byte.MAX_VALUE}));
+            expected.put("ShortArray", new ShortArrayTag(new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE}));
+            expected.put("DoubleArray", new DoubleArrayTag(new double[]{Double.NaN, Double.NEGATIVE_INFINITY, Double.MIN_VALUE, 0, Double.MAX_VALUE, Double.POSITIVE_INFINITY}));
+
+            ListTag listTag = new ListTag();
+            listTag.addTag(new IntTag(0));
+            listTag.addTag(new IntTag(1));
+            listTag.addTag(new IntTag(2));
+            listTag.addTag(new IntTag(3));
+            listTag.addTag(new IntTag(4));
+            expected.put("List", listTag);
+
+            Assertions.assertEquals(expected, exampleData);
+        } catch (IOException e) {
+            Assertions.fail("Failed to read compressed example tag 'allTags_1_0_0.dat'", e);
+        }
+
+        try {
+            CompoundTag exampleData = NbtIo.readCompressed(TestNbtIo.class.getResourceAsStream("/examples/compressed/level.dat"));
+            CompoundTag expected = new CompoundTag();
+            CompoundTag Data = new CompoundTag();
+
+            {
+                CompoundTag GameRules = new CompoundTag();
+                GameRules.putBoolean("allowSleeping", true);
+                GameRules.putBoolean("allowSprinting", false);
+                GameRules.putBoolean("doDaylightCycle", true);
+                GameRules.putBoolean("doNightmares", true);
+                GameRules.putBoolean("doSeasonalGrowth", true);
+                GameRules.putBoolean("dwarfMode", false);
+                GameRules.putBoolean("instantHealing", false);
+                GameRules.putBoolean("keepInventory", false);
+                GameRules.putBoolean("mobGriefing", true);
+                GameRules.putBoolean("treecapitator", false);
+                Data.put("GameRules", GameRules);
+            }
+
+            {
+                CompoundTag Player = new CompoundTag();
+
+                ListTag Motion = new ListTag();
+                Motion.addTag(new DoubleTag(-3.693745721752247E-08D));
+                Motion.addTag(new DoubleTag(-0.0784D));
+                Motion.addTag(new DoubleTag(-3.1104333276149703E-08D));
+                Player.put("Motion", Motion);
+
+                ListTag Pos = new ListTag();
+                Pos.addTag(new DoubleTag(-255.1804810773446));
+                Pos.addTag(new DoubleTag(157.62000000476837));
+                Pos.addTag(new DoubleTag(-251.93904820770453));
+                Player.put("Pos", Pos);
+
+                ListTag Rotation = new ListTag();
+                Rotation.addTag(new FloatTag(108.19741F));
+                Rotation.addTag(new FloatTag(9.819301F));
+                Player.put("Rotation", Rotation);
+
+                Player.putShort("Air", (short) 300);
+                Player.putShort("AttackTime", (short) 0);
+                Player.putByte("ChatColor", (byte) 0);
+                Player.putShort("DeathTime", (short) 0);
+                Player.putInt("Dimension", 0);
+                Player.putFloat("FallDistance", 0);
+                Player.putShort("Fire", (short) -20);
+                Player.putInt("Gamemode", 0);
+                Player.putShort("Health", (short) 9);
+                Player.putShort("HurtTime", (short) 0);
+                Player.putString("Nickname", "");
+                Player.putBoolean("Noclip", false);
+                Player.putBoolean("OnGround", true);
+                Player.putInt("Score", 29750);
+                Player.putByte("SkinVariant", (byte) 59);
+                Player.putBoolean("Sleeping", false);
+                Player.putShort("SleepTimer", (short) 0);
+                Player.putInt("SpawnX", -249);
+                Player.putInt("SpawnY", 163);
+                Player.putInt("SpawnZ", -251);
+
+                Data.put("Player", Player);
+            }
+
+            Data.putBoolean("CheatsEnabled", false);
+            Data.putLong("LastPlayed", 1722422564254L);
+            Data.putString("LevelName", "7.2 World");
+            Data.putLong("RandomSeed", -3160577061770148618L);
+            Data.putLong("SizeOnDisk", 23212032L);
+            Data.putInt("SpawnX", -191);
+            Data.putInt("SpawnY", 129);
+            Data.putInt("SpawnZ", -391);
+            Data.putLong("Time", 189025L);
+            Data.putInt("version", 19134);
+
+            expected.put("Data", Data);
+
+            Assertions.assertEquals(expected, exampleData);
+        } catch (IOException e) {
+            Assertions.fail("Failed to read compressed example tag 'level.dat'!", e);
+        }
+
+        try {
+            CompoundTag exampleData = NbtIo.readCompressed(TestNbtIo.class.getResourceAsStream("/examples/compressed/dimension.dat"));
+            CompoundTag expected = new CompoundTag();
+            CompoundTag Data = new CompoundTag();
+
+            {
+                CompoundTag Weather = new CompoundTag();
+                Weather.putInt("CurrentID", 1);
+                Weather.putLong("Duration", 3082);
+                Weather.putFloat("Intensity", 1);
+                Weather.putInt("NextID", -1);
+                Weather.putFloat("Power", 0.8544321F);
+                Data.put("Weather", Weather);
+            }
+
+            Data.putString("WorldType", "minecraft:overworld.extended");
+            expected.put("Data", Data);
+
+            Assertions.assertEquals(expected, exampleData);
+        } catch (IOException e) {
+            Assertions.fail("Failed to read compressed example tag 'dimension.dat'!", e);
+        }
+    }
+
+    @Test
+    @DisplayName("readUncompressedExamples")
+    public void readUncompressedExamples() {
+        try {
+            CompoundTag exampleData = NbtIo.read(new DataInputStream(TestNbtIo.class.getResourceAsStream("/examples/uncompressed/helloWorld.dat")));
+            CompoundTag expected = new CompoundTag();
+            expected.putString("Hello", "World!");
+
+            Assertions.assertEquals(expected, exampleData);
+        } catch (IOException e) {
+            Assertions.fail("Failed to read uncompressed example tag 'helloWorld.dat'", e);
+        }
+
+        try {
+            CompoundTag exampleData = NbtIo.read(new DataInputStream(TestNbtIo.class.getResourceAsStream("/examples/uncompressed/allTags_1_0_0.dat")));
+            CompoundTag expected = new CompoundTag();
+            expected.put("String", new StringTag("String"));
+            expected.put("Byte", new ByteTag(Byte.MAX_VALUE));
+            expected.put("Short", new ShortTag(Short.MAX_VALUE));
+            expected.put("Int", new IntTag(Integer.MAX_VALUE));
+            expected.put("Long", new LongTag(Long.MAX_VALUE));
+            expected.put("Float", new FloatTag(Float.MAX_VALUE));
+            expected.put("Double", new DoubleTag(Double.MAX_VALUE));
+            expected.put("ByteArray", new ByteArrayTag(new byte[]{Byte.MIN_VALUE, 0, Byte.MAX_VALUE}));
+            expected.put("ShortArray", new ShortArrayTag(new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE}));
+            expected.put("DoubleArray", new DoubleArrayTag(new double[]{Double.NaN, Double.NEGATIVE_INFINITY, Double.MIN_VALUE, 0, Double.MAX_VALUE, Double.POSITIVE_INFINITY}));
+
+            ListTag listTag = new ListTag();
+            listTag.addTag(new IntTag(0));
+            listTag.addTag(new IntTag(1));
+            listTag.addTag(new IntTag(2));
+            listTag.addTag(new IntTag(3));
+            listTag.addTag(new IntTag(4));
+            expected.put("List", listTag);
+
+            Assertions.assertEquals(expected, exampleData);
+        } catch (IOException e) {
+            Assertions.fail("Failed to read uncompressed example tag 'allTags_1_0_0.dat'", e);
+        }
+    }
+
+    @SuppressWarnings("ResultOfMethodCallIgnored")
+    @Test
+    @DisplayName("Test NBT read back")
+    public void ioTest() {
+        File out = new File("./testWork");
+        out.mkdirs();
+        File fileOut = new File(out, "test.dat");
+        {
+
+            CompoundTag dataTag = new CompoundTag();
+            dataTag.putString("Hello", "World!");
+
+            fileOut.delete();
+            try {
+                NbtIo.write(dataTag, new DataOutputStream(Files.newOutputStream(fileOut.toPath())));
+            } catch (IOException e) {
+                Assertions.fail("Failed to write uncompressed test tag!", e);
+            }
+            try {
+                CompoundTag readBackTag = NbtIo.read(new DataInputStream(Files.newInputStream(fileOut.toPath())));
+                Assertions.assertEquals(dataTag, readBackTag);
+            } catch (IOException e) {
+                Assertions.fail("Failed to read uncompressed test tag!", e);
+            }
+            fileOut.delete();
+
+            try {
+                NbtIo.writeCompressed(dataTag, new DataOutputStream(Files.newOutputStream(fileOut.toPath())));
+            } catch (IOException e) {
+                Assertions.fail("Failed to write compressed test tag!", e);
+            }
+            try {
+                CompoundTag readBackTag = NbtIo.readCompressed(Files.newInputStream(fileOut.toPath()));
+                Assertions.assertEquals(dataTag, readBackTag);
+            } catch (IOException e) {
+                Assertions.fail("Failed to read compressed test tag!", e);
+            }
+            fileOut.delete();
+        }
+
+        {
+            CompoundTag dataTag = new CompoundTag();
+            dataTag.put("String", new StringTag("String"));
+            dataTag.put("Byte", new ByteTag(Byte.MAX_VALUE));
+            dataTag.put("Short", new ShortTag(Short.MAX_VALUE));
+            dataTag.put("Int", new IntTag(Integer.MAX_VALUE));
+            dataTag.put("Long", new LongTag(Long.MAX_VALUE));
+            dataTag.put("Float", new FloatTag(Float.MAX_VALUE));
+            dataTag.put("Double", new DoubleTag(Double.MAX_VALUE));
+            dataTag.put("ByteArray", new ByteArrayTag(new byte[]{Byte.MIN_VALUE, 0, Byte.MAX_VALUE}));
+            dataTag.put("ShortArray", new ShortArrayTag(new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE}));
+//        tag.put("IntArray", new IntArrayTag(new int[]{Integer.MIN_VALUE, 0, Integer.MAX_VALUE}));
+            dataTag.put("LongArray", new LongArrayTag(new long[]{Long.MIN_VALUE, 0, Long.MAX_VALUE}));
+//        tag.put("FloatArray", new FloatArrayTag(new float[]{Float.NaN, Float.NEGATIVE_INFINITY, Float.MIN_VALUE, 0, Float.MAX_VALUE, Float.POSITIVE_INFINITY}));
+            dataTag.put("DoubleArray", new DoubleArrayTag(new double[]{Double.NaN, Double.NEGATIVE_INFINITY, Double.MIN_VALUE, 0, Double.MAX_VALUE, Double.POSITIVE_INFINITY}));
+
+            ListTag listTag = new ListTag();
+            listTag.addTag(new IntTag(0));
+            listTag.addTag(new IntTag(1));
+            listTag.addTag(new IntTag(2));
+            listTag.addTag(new IntTag(3));
+            listTag.addTag(new IntTag(4));
+            dataTag.put("List", listTag);
+
+
+            fileOut.delete();
+            try {
+                NbtIo.write(dataTag, new DataOutputStream(Files.newOutputStream(fileOut.toPath())));
+            } catch (IOException e) {
+                Assertions.fail("Failed to write uncompressed test tag!", e);
+            }
+            try {
+                CompoundTag readBackTag = NbtIo.read(new DataInputStream(Files.newInputStream(fileOut.toPath())));
+                Assertions.assertEquals(dataTag, readBackTag);
+            } catch (IOException e) {
+                Assertions.fail("Failed to read uncompressed test tag!", e);
+            }
+            fileOut.delete();
+
+            try {
+                NbtIo.writeCompressed(dataTag, new DataOutputStream(Files.newOutputStream(fileOut.toPath())));
+            } catch (IOException e) {
+                Assertions.fail("Failed to write compressed test tag!", e);
+            }
+            try {
+                CompoundTag readBackTag = NbtIo.readCompressed(Files.newInputStream(fileOut.toPath()));
+                Assertions.assertEquals(dataTag, readBackTag);
+            } catch (IOException e) {
+                Assertions.fail("Failed to read compressed test tag!", e);
+            }
+            fileOut.delete();
+        }
+    }
+}
diff --git a/util/nbt/src/test/java/TestShortArrayTag.java b/util/nbt/src/test/java/TestShortArrayTag.java
new file mode 100644
index 000000000..aae887f1d
--- /dev/null
+++ b/util/nbt/src/test/java/TestShortArrayTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.ShortArrayTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestShortArrayTag {
+    @Test
+    public void testTag() {
+        ShortArrayTag shortArrayTagEmpty = new ShortArrayTag();
+        Assertions.assertEquals(shortArrayTagEmpty.getId(), 11, "Tag id does not match its expected id!");
+        Assertions.assertArrayEquals(new short[0], shortArrayTagEmpty.getValue(), "Default short array tag value should be and empty array!");
+
+        ShortArrayTag shortArrayTag1 = new ShortArrayTag(new short[]{-1, 0, 2, 7, 9, Short.MIN_VALUE, 0, Short.MAX_VALUE});
+        Assertions.assertArrayEquals(new short[]{-1, 0, 2, 7, 9, Short.MIN_VALUE, 0, Short.MAX_VALUE}, shortArrayTag1.getValue(), "Tag value does not match its equivalent array!");
+
+        ShortArrayTag shortArrayTag2 = new ShortArrayTag(new short[]{-1, 0, 2, 7, 9, Short.MIN_VALUE, 0, Short.MAX_VALUE});
+        Assertions.assertEquals(shortArrayTag2, shortArrayTag1, "Tag value does not equal its equivalent tag!");
+
+        ShortArrayTag shortArrayTag3 = new ShortArrayTag(new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE, 9, 7, 2, 0, -1});
+        Assertions.assertNotEquals(shortArrayTag3, shortArrayTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestShortTag.java b/util/nbt/src/test/java/TestShortTag.java
new file mode 100644
index 000000000..d221c82d4
--- /dev/null
+++ b/util/nbt/src/test/java/TestShortTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.ShortTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestShortTag {
+    @Test
+    public void testTag() {
+        ShortTag shortTagEmpty = new ShortTag();
+        Assertions.assertEquals(shortTagEmpty.getId(), 2, "Tag id does not match its expected id!");
+        Assertions.assertEquals(shortTagEmpty.getValue(), (short) 0, "Default short tag value should be 0!");
+
+        ShortTag shortTag1 = new ShortTag(Short.MAX_VALUE);
+        Assertions.assertEquals(Short.MAX_VALUE, shortTag1.getValue(), "Tag value does not match its equivalent value!");
+
+        ShortTag shortTag2 = new ShortTag(Short.MAX_VALUE);
+        Assertions.assertEquals(shortTag2, shortTag1, "Tag value does not equal its equivalent tag!");
+
+        ShortTag shortTag3 = new ShortTag(Short.MIN_VALUE);
+        Assertions.assertNotEquals(shortTag3, shortTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestStringTag.java b/util/nbt/src/test/java/TestStringTag.java
new file mode 100644
index 000000000..70b7faedc
--- /dev/null
+++ b/util/nbt/src/test/java/TestStringTag.java
@@ -0,0 +1,21 @@
+import com.mojang.nbt.tags.StringTag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestStringTag {
+    @Test
+    public void testTag() {
+        StringTag stringTagEmpty = new StringTag();
+        Assertions.assertEquals(stringTagEmpty.getId(), 8, "Tag id does not match its expected id!");
+        Assertions.assertEquals(stringTagEmpty.getValue(), "", "Default string tag value should be \"\"!");
+
+        StringTag stringTag1 = new StringTag("Hello World!");
+        Assertions.assertEquals("Hello World!", stringTag1.getValue(), "Tag value does not match its equivalent value!");
+
+        StringTag stringTag2 = new StringTag("Hello World!");
+        Assertions.assertEquals(stringTag2, stringTag1, "Tag value does not equal its equivalent tag!");
+
+        StringTag stringTag3 = new StringTag("");
+        Assertions.assertNotEquals(stringTag3, stringTag2, "Tag equals non equivalent tag!");
+    }
+}
diff --git a/util/nbt/src/test/java/TestTag.java b/util/nbt/src/test/java/TestTag.java
new file mode 100644
index 000000000..b66c41579
--- /dev/null
+++ b/util/nbt/src/test/java/TestTag.java
@@ -0,0 +1,97 @@
+import com.mojang.nbt.tags.ByteArrayTag;
+import com.mojang.nbt.tags.ByteTag;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.DoubleArrayTag;
+import com.mojang.nbt.tags.DoubleTag;
+import com.mojang.nbt.tags.EndTag;
+import com.mojang.nbt.tags.FloatTag;
+import com.mojang.nbt.tags.IntTag;
+import com.mojang.nbt.tags.ListTag;
+import com.mojang.nbt.tags.LongArrayTag;
+import com.mojang.nbt.tags.LongTag;
+import com.mojang.nbt.tags.ShortArrayTag;
+import com.mojang.nbt.tags.ShortTag;
+import com.mojang.nbt.tags.StringTag;
+import com.mojang.nbt.tags.Tag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class TestTag {
+    @Test
+    public void testTagNames() {
+        Assertions.assertEquals("TAG_End", Tag.getTagName((byte) 0));
+        Assertions.assertEquals("TAG_Byte", Tag.getTagName((byte) 1));
+        Assertions.assertEquals("TAG_Short", Tag.getTagName((byte) 2));
+        Assertions.assertEquals("TAG_Int", Tag.getTagName((byte) 3));
+        Assertions.assertEquals("TAG_Long", Tag.getTagName((byte) 4));
+        Assertions.assertEquals("TAG_Float", Tag.getTagName((byte) 5));
+        Assertions.assertEquals("TAG_Double", Tag.getTagName((byte) 6));
+        Assertions.assertEquals("TAG_Byte_Array", Tag.getTagName((byte) 7));
+        Assertions.assertEquals("TAG_String", Tag.getTagName((byte) 8));
+        Assertions.assertEquals("TAG_List", Tag.getTagName((byte) 9));
+        Assertions.assertEquals("TAG_Compound", Tag.getTagName((byte) 10));
+        Assertions.assertEquals("TAG_Short_Array", Tag.getTagName((byte) 11));
+        Assertions.assertEquals("TAG_Double_Array", Tag.getTagName((byte) 12));
+        Assertions.assertEquals("TAG_Long_Array", Tag.getTagName((byte) 13));
+        Assertions.assertThrows(IllegalArgumentException.class, () -> Tag.getTagName((byte) - 1));
+    }
+
+    @Test
+    public void testTagTypes() {
+        Assertions.assertInstanceOf(EndTag.class, Tag.newTag((byte) 0));
+        Assertions.assertInstanceOf(ByteTag.class, Tag.newTag((byte) 1));
+        Assertions.assertInstanceOf(ShortTag.class, Tag.newTag((byte) 2));
+        Assertions.assertInstanceOf(IntTag.class, Tag.newTag((byte) 3));
+        Assertions.assertInstanceOf(LongTag.class, Tag.newTag((byte) 4));
+        Assertions.assertInstanceOf(FloatTag.class, Tag.newTag((byte) 5));
+        Assertions.assertInstanceOf(DoubleTag.class, Tag.newTag((byte) 6));
+        Assertions.assertInstanceOf(ByteArrayTag.class, Tag.newTag((byte) 7));
+        Assertions.assertInstanceOf(StringTag.class, Tag.newTag((byte) 8));
+        Assertions.assertInstanceOf(ListTag.class, Tag.newTag((byte) 9));
+        Assertions.assertInstanceOf(CompoundTag.class, Tag.newTag((byte) 10));
+        Assertions.assertInstanceOf(ShortArrayTag.class, Tag.newTag((byte) 11));
+        Assertions.assertInstanceOf(DoubleArrayTag.class, Tag.newTag((byte) 12));
+        Assertions.assertInstanceOf(LongArrayTag.class, Tag.newTag((byte) 13));
+        Assertions.assertThrows(IllegalArgumentException.class, () -> Tag.newTag((byte) - 1));
+    }
+
+    @Test
+    public void testTagGenerics() {
+        Assertions.assertInstanceOf(ByteTag.class, Tag.createTagOfType(byte.class));
+        Assertions.assertInstanceOf(ByteTag.class, Tag.createTagOfType(Byte.class));
+        Assertions.assertInstanceOf(ShortTag.class, Tag.createTagOfType(short.class));
+        Assertions.assertInstanceOf(ShortTag.class, Tag.createTagOfType(Short.class));
+        Assertions.assertInstanceOf(IntTag.class, Tag.createTagOfType(int.class));
+        Assertions.assertInstanceOf(IntTag.class, Tag.createTagOfType(Integer.class));
+        Assertions.assertInstanceOf(LongTag.class, Tag.createTagOfType(long.class));
+        Assertions.assertInstanceOf(LongTag.class, Tag.createTagOfType(Long.class));
+        Assertions.assertInstanceOf(FloatTag.class, Tag.createTagOfType(float.class));
+        Assertions.assertInstanceOf(FloatTag.class, Tag.createTagOfType(Float.class));
+        Assertions.assertInstanceOf(DoubleTag.class, Tag.createTagOfType(double.class));
+        Assertions.assertInstanceOf(DoubleTag.class, Tag.createTagOfType(Double.class));
+        Assertions.assertInstanceOf(ByteArrayTag.class, Tag.createTagOfType(byte[].class));
+        Assertions.assertInstanceOf(ByteArrayTag.class, Tag.createTagOfType(Byte[].class));
+        Assertions.assertInstanceOf(StringTag.class, Tag.createTagOfType(String.class));
+        Assertions.assertInstanceOf(ListTag.class, Tag.createTagOfType(List.class));
+        Assertions.assertInstanceOf(ListTag.class, Tag.createTagOfType(ArrayList.class));
+        Assertions.assertInstanceOf(ListTag.class, Tag.createTagOfType(LinkedList.class));
+        Assertions.assertInstanceOf(CompoundTag.class, Tag.createTagOfType(Map.class));
+        Assertions.assertInstanceOf(CompoundTag.class, Tag.createTagOfType(HashMap.class));
+        Assertions.assertInstanceOf(CompoundTag.class, Tag.createTagOfType(Hashtable.class));
+        Assertions.assertInstanceOf(ShortArrayTag.class, Tag.createTagOfType(short[].class));
+        Assertions.assertInstanceOf(ShortArrayTag.class, Tag.createTagOfType(Short[].class));
+        Assertions.assertInstanceOf(DoubleArrayTag.class, Tag.createTagOfType(double[].class));
+        Assertions.assertInstanceOf(DoubleArrayTag.class, Tag.createTagOfType(Double[].class));
+        Assertions.assertInstanceOf(LongArrayTag.class, Tag.createTagOfType(long[].class));
+        Assertions.assertInstanceOf(LongArrayTag.class, Tag.createTagOfType(Long[].class));
+        Assertions.assertThrows(IllegalArgumentException.class, () -> Tag.createTagOfType(Thread.class));
+        Assertions.assertThrows(IllegalArgumentException.class, () -> Tag.createTagOfType(Thread[].class));
+    }
+}
diff --git a/util/nbt/src/test/resources/examples/compressed/allTags_1_0_0.dat b/util/nbt/src/test/resources/examples/compressed/allTags_1_0_0.dat
new file mode 100644
index 000000000..49a57f2c1
Binary files /dev/null and b/util/nbt/src/test/resources/examples/compressed/allTags_1_0_0.dat differ
diff --git a/util/nbt/src/test/resources/examples/compressed/dimension.dat b/util/nbt/src/test/resources/examples/compressed/dimension.dat
new file mode 100644
index 000000000..6d7326145
Binary files /dev/null and b/util/nbt/src/test/resources/examples/compressed/dimension.dat differ
diff --git a/util/nbt/src/test/resources/examples/compressed/helloWorld.dat b/util/nbt/src/test/resources/examples/compressed/helloWorld.dat
new file mode 100644
index 000000000..25a3d0ba2
Binary files /dev/null and b/util/nbt/src/test/resources/examples/compressed/helloWorld.dat differ
diff --git a/util/nbt/src/test/resources/examples/compressed/level.dat b/util/nbt/src/test/resources/examples/compressed/level.dat
new file mode 100644
index 000000000..b1d97b5af
Binary files /dev/null and b/util/nbt/src/test/resources/examples/compressed/level.dat differ
diff --git a/util/nbt/src/test/resources/examples/uncompressed/allTags_1_0_0.dat b/util/nbt/src/test/resources/examples/uncompressed/allTags_1_0_0.dat
new file mode 100644
index 000000000..f5d3287db
Binary files /dev/null and b/util/nbt/src/test/resources/examples/uncompressed/allTags_1_0_0.dat differ
diff --git a/util/nbt/src/test/resources/examples/uncompressed/helloWorld.dat b/util/nbt/src/test/resources/examples/uncompressed/helloWorld.dat
new file mode 100644
index 000000000..897329475
Binary files /dev/null and b/util/nbt/src/test/resources/examples/uncompressed/helloWorld.dat differ
diff --git a/util/seed-viewer/build.gradle.kts b/util/seed-viewer/build.gradle.kts
index d901f9c79..460853a3b 100644
--- a/util/seed-viewer/build.gradle.kts
+++ b/util/seed-viewer/build.gradle.kts
@@ -21,6 +21,8 @@ dependencies {
     testImplementation("org.junit.jupiter:junit-jupiter")
 
     implementation(project(":game:core"))?.let { include(it) }
+    implementation(project(":util:logging"))?.let { include(it) }
+    implementation(project(":util:nbt"))?.let { include(it) }
 
     implementation(libs.jetbrains.annotations)?.let { include(it) }
     implementation(libs.bundles.log4j)?.let { include(it) }
diff --git a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/chunk/provider/ChunkProviderSeedViewer.java b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/chunk/provider/ChunkProviderSeedViewer.java
index c46feaf47..4bb459ef5 100644
--- a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/chunk/provider/ChunkProviderSeedViewer.java
+++ b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/chunk/provider/ChunkProviderSeedViewer.java
@@ -10,7 +10,6 @@ import net.minecraft.core.world.chunk.provider.IChunkProvider;
 import net.minecraft.core.world.generate.chunk.ChunkGenerator;
 import org.slf4j.Logger;
 
-import java.io.IOException;
 import java.util.Arrays;
 
 public class ChunkProviderSeedViewer
diff --git a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/ChunkLoader.java b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/ChunkLoader.java
index 5712fabc2..91030b157 100644
--- a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/ChunkLoader.java
+++ b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/ChunkLoader.java
@@ -1,7 +1,7 @@
 package org.useless.seedviewer.bta.worldloader;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.ProgressListener;
 import net.minecraft.core.world.World;
diff --git a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/DimensionDataLoader.java b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/DimensionDataLoader.java
index cb7a5026c..cc8069d74 100644
--- a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/DimensionDataLoader.java
+++ b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/DimensionDataLoader.java
@@ -1,7 +1,7 @@
 package org.useless.seedviewer.bta.worldloader;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.save.DimensionData;
 import org.jetbrains.annotations.NotNull;
diff --git a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/LevelDataLoader.java b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/LevelDataLoader.java
index 991d09397..a80c5f5c5 100644
--- a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/LevelDataLoader.java
+++ b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/worldloader/LevelDataLoader.java
@@ -1,7 +1,7 @@
 package org.useless.seedviewer.bta.worldloader;
 
 import com.mojang.logging.LogUtils;
-import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.save.LevelData;
 import org.jetbrains.annotations.NotNull;
