diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
index 0b8f22128..224ca0a73 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
@@ -263,10 +263,12 @@ public abstract class ScreenContainerAbstract extends Screen {
             // Duplicate items with middle mouse button
             if (buttonNum == 2) {
                 Slot slot = this.inventorySlots.getSlot(getSlotId(mx, my));
-                if (slot.getItemStack() == null) {
-                    this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.SORT, new int[]{slot.index, 64}, this.mc.thePlayer);
-                } else {
-                    this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, new int[]{slot.index, 64}, this.mc.thePlayer);
+                if (slot != null) {
+                    if (slot.getItemStack() == null) {
+                        this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.SORT, new int[]{slot.index, 64}, this.mc.thePlayer);
+                    } else {
+                        this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, new int[]{slot.index, 64}, this.mc.thePlayer);
+                    }
                 }
                 return;
             }
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/slime/slime.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/slime/slime.geo.json
index d9a16c175..2777a354c 100644
--- a/game/client/src/main/resources/assets/minecraft/models/entity/slime/slime.geo.json
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/slime/slime.geo.json
@@ -6,7 +6,14 @@
 		"visible_bounds_width": 5,
 		"visible_bounds_height": 2,
 		"visible_bounds_offset": [0, 1, 0],
-		"bones": [
+		"bones": [{
+				"name": "mouth",
+				"parent": "cube",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8]}
+				]
+			},
 			{
 				"name": "cube",
 				"pivot": [0, 24, 0],
@@ -16,14 +23,6 @@
 					{"origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4]},
 					{"origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0]}
 				]
-			},
-			{
-				"name": "mouth",
-				"parent": "cube",
-				"pivot": [0, 24, 0],
-				"cubes": [
-					{"origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8]}
-				]
 			}
 		]
 	}
diff --git a/game/client/src/main/resources/shaders/font.fsh b/game/client/src/main/resources/shaders/font.fsh
index 229c9771e..cef7a585a 100644
--- a/game/client/src/main/resources/shaders/font.fsh
+++ b/game/client/src/main/resources/shaders/font.fsh
@@ -1,4 +1,13 @@
 #version 410 core
+
+#define MASK_ITALIC 0x01u
+#define MASK_UNDERLINE 0x02u
+#define MASK_STRIKETHROUGH 0x04u
+#define MASK_BOLD 0x08u
+#define MASK_OBFUSCATED 0x10u
+#define MASK_OUTLINE 0x20u
+#define MASK_SHADOW 0x80u
+
 out vec4 FragColor;
 
 in vec4 Color;
@@ -28,15 +37,15 @@ vec4 colorAtPoint(vec2 point) {
         color = texture(colortex, point) * Color * tint;
     }
     vec2 left = point - vec2(1, 0)/128;
-    if ((config & 0x08u) != 0 && sampleInside(left) && length(color) == 0) {
+    if ((config & MASK_BOLD) != 0 && sampleInside(left) && length(color) == 0) {
         color = texture(colortex, left) * Color * tint;
     }
     vec2 max = UV + (Size/128);
-    if ((config & 0x02u) != 0 && point.y > max.y && point.y < (max.y + 1.0/128)) {
+    if ((config & MASK_UNDERLINE) != 0 && point.y > max.y && point.y < (max.y + 1.0/128)) {
         color = Color * tint;
     }
     vec2 mid = UV + Size/256;
-    if ((config & 0x04u) != 0 && point.y > (mid.y - 1.0/128) && point.y < mid.y) {
+    if ((config & MASK_STRIKETHROUGH) != 0 && point.y > (mid.y - 1.0/128) && point.y < mid.y) {
         color = Color * tint;
     }
 
@@ -45,7 +54,8 @@ vec4 colorAtPoint(vec2 point) {
 
 
 bool canReplace(vec2 tex) {
-    return length(colorAtPoint(tex)) != 0;
+    vec4 c = colorAtPoint(tex);
+    return c.a > 0.1;
 }
 
 
@@ -53,8 +63,8 @@ void main() {
     uint config = uint(Config + 0.01);
     vec4 tint = texture(lighttex, Lightmap) * uColor;
     FragColor = colorAtPoint(TexCoord);
-    if (length(FragColor) == 0) {
-        if ((config & 0x20u) != 0) {
+    if (FragColor.a < 0.1) {
+        if ((config & MASK_OUTLINE) != 0) {
             vec2 upLeft = TexCoord + vec2(-1, -1)/128;
             vec2 up = TexCoord + vec2(0, -1)/128;
             vec2 upRight = TexCoord + vec2(1, -1)/128;
@@ -66,7 +76,7 @@ void main() {
             if (canReplace(upLeft) || canReplace(up) || canReplace(upRight) || canReplace(left) || canReplace(right) || canReplace(downLeft) || canReplace(down) || canReplace(downRight)) {
                 FragColor = vec4(Color.rgb/4, Color.a) * tint;
             }
-        } else if ((config & 0x80u) != 0) {
+        } else if ((config & MASK_SHADOW) != 0) {
             vec2 upLeft = TexCoord - vec2(1, 1)/128;
             if (canReplace(upLeft)) {
                 FragColor = vec4(Color.rgb/4, Color.a) * tint;
diff --git a/game/client/src/main/resources/shaders/font.gsh b/game/client/src/main/resources/shaders/font.gsh
index f036b47c1..4c66c0308 100644
--- a/game/client/src/main/resources/shaders/font.gsh
+++ b/game/client/src/main/resources/shaders/font.gsh
@@ -1,4 +1,13 @@
 #version 410 core
+
+#define MASK_ITALIC 0x01u
+#define MASK_UNDERLINE 0x02u
+#define MASK_STRIKETHROUGH 0x04u
+#define MASK_BOLD 0x08u
+#define MASK_OBFUSCATED 0x10u
+#define MASK_OUTLINE 0x20u
+#define MASK_SHADOW 0x80u
+
 layout (points) in;
 layout (triangle_strip, max_vertices = 4) out;
 
@@ -32,7 +41,7 @@ void main() {
     Color = gs_in[0].color;
     Lightmap = gs_in[0].lightmap;
 
-    float shift = uint(gs_in[0].config) & 0x01u;
+    float shift = uint(gs_in[0].config) & MASK_ITALIC;
 
     TexCoord = gs_in[0].uv + vec2(-1, gs_in[0].size.y + 2)/128;
     gl_Position = matrices.projection * matrices.view * model * (gl_in[0].gl_Position + vec4(-shift - 1,  gs_in[0].size.y + 2, 0.0, 0.0));
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSand.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSand.java
index f30407594..40e14f78c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSand.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSand.java
@@ -62,7 +62,7 @@ public class BlockLogicSand extends BlockLogic {
 
     public static boolean canFallBelow(@NotNull World world, @NotNull TilePos tilePos) {
         Block<?> block = world.getBlockType(tilePos);
-        return block == null || block.hasTag(BlockTags.PLACE_OVERWRITES);
+        return block == Blocks.AIR || block.hasTag(BlockTags.PLACE_OVERWRITES);
     }
 
 }
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 440d6f081..44c9fa74e 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
@@ -21,7 +21,7 @@ public abstract class TileEntity implements ICarriable
 {
     public @Nullable World worldObj; // Null when loading data from nbt and null when held by entity
     public @Nullable CarriedBlock carriedBlock;
-    public int x;
+    public int x; // TODO replace with tilePos
     public int y;
     public int z;
     protected boolean tileEntityInvalid;
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 62c060903..316bef176 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
@@ -17,7 +17,7 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class CarriedBlock implements ICarriable {
-    public int blockId;
+    public int blockId; // TODO replace with direct block ref
     public int metadata;
     public @Nullable TileEntity entity;
     // Ignore warnings, nbt read process *should* guarantee these to be non-null
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 9ec9c62f4..00c2abe4a 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
@@ -17,6 +17,7 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.IVehicle;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.pos.TilePos;
+import net.minecraft.core.world.pos.TilePosc;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -106,23 +107,21 @@ public class EntityFallingBlock extends Entity
         this.xd *= 0.98D;
         this.yd *= 0.98D;
         this.zd *= 0.98D;
-        int x = MathHelper.round(this.x - 0.5);
-        int y = MathHelper.round(this.y);
-        int z = MathHelper.round(this.z - 0.5);
-        if(this.world.getBlockId(x, y, z) == this.carriedBlock.blockId && !this.hasRemovedBlock)
+        TilePosc blockPos = roundedPos();
+        if(this.world.getBlockType(blockPos).id() == this.carriedBlock.blockId && !this.hasRemovedBlock)
         {
-            this.world.setBlockWithNotify(x, y, z, 0);
+            this.world.setBlockTypeNotify(blockPos, Blocks.AIR);
             this.hasRemovedBlock = true;
         }
         if (this.onGround) {
             Block<?> selfBlock = this.carriedBlock.block();
-            Block<?> blockBelow = this.world.getBlock(x, y - 1, z);
-            Block<?> blockAt = this.world.getBlock(x, y, z);
+            Block<?> blockBelow = this.world.getBlockType(blockPos.down(new TilePos()));
+            Block<?> blockAt = this.world.getBlockType(blockPos);
             double friction = selfBlock.friction;
             if (BlockTags.OVERRIDE_FRICTION.appliesTo(blockAt)) {
-                friction *= blockAt.friction * 0.91f;
-            } else if (blockBelow != null) {
-                friction *= blockBelow.friction * 0.91f;
+                friction *= blockAt.friction * 0.91;
+            } else if (blockBelow != Blocks.AIR) {
+                friction *= blockBelow.friction * 0.91;
             } else {
                 friction *= 0.98;
             }
@@ -139,31 +138,31 @@ public class EntityFallingBlock extends Entity
                 Entity rider = getPassenger();
                 ejectRider();
                 remove();
-                if((!this.world.canBlockBePlacedAt(this.carriedBlock.blockId, x, y, z, true, Side.TOP) || BlockLogicSand.canFallBelow(this.world, new TilePos(x, y - 1, z)) || !this.world.setBlock(x, y, z, this.carriedBlock.blockId)) && !this.world.isClientSide)
+                if((!this.world.canBlockIdBePlacedAt(this.carriedBlock.blockId, blockPos, true, Side.TOP) || BlockLogicSand.canFallBelow(this.world, blockPos.down(new TilePos())) || !this.world.setBlockType(blockPos, Blocks.getBlock(this.carriedBlock.blockId))) && !this.world.isClientSide)
                 {
                     if(this.hasRemovedBlock) {
                         drop();
                     }
                 } else if (!this.world.isClientSide) {
-                    this.world.setBlockMetadata(x, y, z, this.carriedBlock.metadata);
+                    this.world.setBlockData(blockPos, this.carriedBlock.metadata);
                     if (this.carriedBlock.entity != null) {
-                        TileEntity oldEnt = this.world.getTileEntity(x, y, z);
+                        TileEntity oldEnt = this.world.getTileEntity(blockPos);
                         if (oldEnt != null) {
                             oldEnt.invalidate();
                         }
                         this.carriedBlock.entity.validate();
-                        this.carriedBlock.entity.x = x;
-                        this.carriedBlock.entity.y = y;
-                        this.carriedBlock.entity.z = z;
+                        this.carriedBlock.entity.x = blockPos.x();
+                        this.carriedBlock.entity.y = blockPos.y();
+                        this.carriedBlock.entity.z = blockPos.z();
                         this.carriedBlock.entity.worldObj = this.world;
                         this.carriedBlock.entity.carriedBlock = null;
-                        this.world.replaceBlockTileEntity(x, y, z, this.carriedBlock.entity);
+                        this.world.replaceTileEntity(blockPos, this.carriedBlock.entity);
                     }
-                    this.world.notifyBlockChange(x, y, z, this.carriedBlock.blockId);
+                    this.world.notifyBlockChange(blockPos, Blocks.getBlock(this.carriedBlock.blockId));
                 }
                 if (rider != null) {
-                    TileEntity te = this.world.getTileEntity(x, y, z);
-                    if (te instanceof IVehicle) rider.startRiding((IVehicle) te);
+                    TileEntity te = this.world.getTileEntity(blockPos);
+                    if (te instanceof IVehicle vehicle) rider.startRiding(vehicle);
                 }
             } else if(this.fallTime > 600 && !this.world.isClientSide) {
                 if(this.hasRemovedBlock) {
@@ -188,10 +187,8 @@ public class EntityFallingBlock extends Entity
             }
         }
         if (this.carriedBlock.entity != null) {
-            int x = MathHelper.round(this.x - 0.5);
-            int y = MathHelper.round(this.y);
-            int z = MathHelper.round(this.z - 0.5);
-            this.carriedBlock.entity.dropContents(this.world, x, y, z);
+            TilePosc blockPos = roundedPos();
+            this.carriedBlock.entity.dropContents(this.world, blockPos.x(), blockPos.y(), blockPos.z());
         }
     }
 
@@ -258,4 +255,8 @@ public class EntityFallingBlock extends Entity
     public double getRideHeight() {
         return 0.0D;
     }
+
+    public @NotNull TilePosc roundedPos() {
+        return new TilePos(MathHelper.round(this.x - 0.5), MathHelper.floor(this.y), MathHelper.round(this.z - 0.5));
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java
index a79170070..ecf125695 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java
@@ -115,7 +115,7 @@ public abstract class MenuAbstract
 	}
 
 
-	public Slot getSlot(int i)
+	public @Nullable Slot getSlot(int i)
 	{
 		try{
 			return slots.get(i);
