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 5e23a8e05..aa13993f6 100644
--- a/game/client/src/main/java/net/minecraft/client/Minecraft.java
+++ b/game/client/src/main/java/net/minecraft/client/Minecraft.java
@@ -80,6 +80,7 @@ import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.core.world.type.WorldType;
 import net.minecraft.core.world.type.WorldTypeGroups;
 
+import javax.crypto.Cipher;
 import javax.imageio.ImageIO;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
@@ -115,9 +116,7 @@ import net.minecraft.client.option.KeyBinding;
 import net.minecraft.client.option.enums.LightmapStyle;
 import net.minecraft.client.player.controller.PlayerController;
 import net.minecraft.client.render.ParticleEngine;
-import net.minecraft.client.render.EntityRenderDispatcher;
 import net.minecraft.client.render.FallbackRenderer;
-import net.minecraft.client.render.ItemRenderer;
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.LoadingScreenRenderer;
 import net.minecraft.client.render.OpenGLHelper;
@@ -288,6 +287,8 @@ public class Minecraft
     private int mojrand = new Random(System.currentTimeMillis()).nextInt(200);
     public TerrainRenderer terrainRenderer;
 
+    private static final TimeKeeper STARTUP_TIKE_KEEPER = new TimeKeeper();
+
     /**
      * Keep this as the only constructor in this class for now,
      * otherwise JVM class verification will fail and the game will crash when the fabric loader tries to run the game.
@@ -465,8 +466,6 @@ public class Minecraft
     
     public void startGame() throws LWJGLException
     {
-        ImageIO.setUseCache(false); // Speeds up boot time
-
         // Initialize LogMessageReceiver to capture output
         LogMessageReceiver.init();
 
@@ -544,8 +543,10 @@ public class Minecraft
         loadScreen();
         
         // Initialize overworld biome map
+        STARTUP_TIKE_KEEPER.start("Biome Provider");
         BiomeProviderOverworld.init();
-        
+        STARTUP_TIKE_KEEPER.end("Biome Provider");
+
         worldRenderer = new WorldRenderer(this);
 
         // I hate initialization issues so much
@@ -665,14 +666,15 @@ public class Minecraft
         } catch (Exception e){
             hasBeta173 = false;
         }
-        
+
+        STARTUP_TIKE_KEEPER.start("JCE Check");
         boolean hasJCE;
         try {
-            AES.encrypt("I hate that prism defaults BTA to 8u51.", AES.generateKey());
-            hasJCE = true;
+            hasJCE = Cipher.getMaxAllowedKeyLength("AES") > 128;
         }catch (final Exception ignored) {
             hasJCE = false;
         }
+        STARTUP_TIKE_KEEPER.end("JCE Check");
 
         if (!hasBeta173) {
             displayScreen(new ScreenMissingMinecraft());
@@ -700,6 +702,8 @@ public class Minecraft
             displayScreen(new ScreenMainMenu());
         }
         gameWindow.updateWindowState();
+        STARTUP_TIKE_KEEPER.end("Startup");
+        LOGGER.info(STARTUP_TIKE_KEEPER.toString());
     }
 
     public void initCommands() {
@@ -934,7 +938,7 @@ public class Minecraft
         if(screen != null)
         {
             setIngameNotInFocus();
-            screen.opened(this, resolution.getScaledWidthScreenCoords(), resolution.getScaledHeightScreenCoords());
+            screen.opened(resolution.getScaledWidthScreenCoords(), resolution.getScaledHeightScreenCoords());
             skipRenderWorld = false;
         } else
         {
@@ -1429,13 +1433,13 @@ public class Minecraft
     {
         resolution.setScale(gameSettings.guiScale.value);
         if(currentScreen != null) {
-            currentScreen.opened(this, resolution.getScaledWidthScreenCoords(), resolution.getScaledHeightScreenCoords());
+            currentScreen.opened(resolution.getScaledWidthScreenCoords(), resolution.getScaledHeightScreenCoords());
         }
     }
 
     private void clickMiddleMouseButton(boolean shift, boolean control)
     {
-        HitResult mouseOver = thePlayer.rayTrace(256, timer.partialTicks, false, false);
+        HitResult mouseOver = thePlayer.rayTrace(256, timer.partialTicks, false, false, false);
         if(mouseOver != null && mouseOver.hitType == HitResult.HitType.TILE)
         {
             int x = mouseOver.x;
@@ -2671,6 +2675,8 @@ public class Minecraft
 
     public static void main(String[] args)
     {
+        STARTUP_TIKE_KEEPER.start("Startup");
+        ImageIO.setUseCache(false); // Speeds up boot time
         checkLwjglVersion();
         if (isClientASteamDeck()) {
             System.out.println("Client is a Steam Deck!");
@@ -2859,4 +2865,35 @@ public class Minecraft
         // Mojang does the exact same as of 1.21.4, so this is reasonably legit.
         System.setProperty("java.awt.headless", "true");
     }
+
+    private static class TimeKeeper {
+        private final @NotNull Map<@NotNull String, @NotNull Long> startTimes = new LinkedHashMap<>();
+        private final @NotNull Map<@NotNull String, @NotNull Long> endTimes = new LinkedHashMap<>();
+
+        public void start(final @NotNull String key) {
+            if (this.startTimes.containsKey(key)) LOGGER.error("Start key {} already assigned", key);
+            this.startTimes.put(key, System.currentTimeMillis());
+        }
+
+        public void end(final @NotNull String key) {
+            if (this.endTimes.containsKey(key)) LOGGER.error("End key {} already assigned", key);
+            this.endTimes.put(key, System.currentTimeMillis());
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder builder = new StringBuilder("Startup Times: ");
+            for (final String s : this.startTimes.keySet()) {
+                if (!this.endTimes.containsKey(s)) {
+                    LOGGER.error("Perf key {} not ended!", s);
+                    continue;
+                }
+                final Long start = this.startTimes.get(s);
+                final Long end = this.endTimes.get(s);
+                if (start == null || end == null) continue;
+                builder.append("\n\t").append(s).append(": ").append((end - start)/1000d).append("s");
+            }
+            return builder.toString();
+        }
+    }
 }
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 106146013..5d16b6db8 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
@@ -48,6 +48,7 @@ import net.minecraft.core.player.gamemode.Gamemode;
 import net.minecraft.core.player.inventory.menu.MenuInventory;
 import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.sound.SoundCategory;
+import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.GetSkinUrlThread;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
@@ -205,10 +206,10 @@ public class PlayerLocal extends Player
         float f = 0.8f;
         boolean forwardInput = input.moveForward >= f;
         input.tick(this);
-        if(input.sneak && ySlideOffset < 0.45F)
-        {
-            ySlideOffset = 0.45F;
-        }
+//        if(input.sneak && ySlideOffset < 0.45F)
+//        {
+//            ySlideOffset = 0.45F;
+//        }
         checkInTile(x - (double) bbWidth * 0.35D, bb.minY + 0.5D, z + (double) bbWidth * 0.35D);
         checkInTile(x - (double) bbWidth * 0.35D, bb.minY + 0.5D, z - (double) bbWidth * 0.35D);
         checkInTile(x + (double) bbWidth * 0.35D, bb.minY + 0.5D, z - (double) bbWidth * 0.35D);
@@ -390,9 +391,9 @@ public class PlayerLocal extends Player
     }
     
     @Override
-    public boolean isSneaking()
+    public boolean wantSneak()
     {
-        return input.sneak && !sleeping;
+        return (input != null && input.sneak) && !sleeping;
     }
 
     public void setHealth(int i)
@@ -454,65 +455,48 @@ public class PlayerLocal extends Player
         return mc.statsCounter.readStat(stat);
     }
 
-    private boolean isBlockTranslucent(int x, int y, int z)
-    {
-        return world.isBlockNormalCube(x, y, z);
-    }
-
     @Override
     protected boolean checkInTile(double x, double y, double z)
     {
-        if (noPhysics) return false;
-        int blockX = MathHelper.floor(x);
-        int blockY = MathHelper.floor(y);
-        int blockZ = MathHelper.floor(z);
-        double d3 = x - (double)blockX;
-        double d4 = z - (double)blockZ;
-        if(isBlockTranslucent(blockX, blockY, blockZ) || (isBlockTranslucent(blockX, blockY + 1, blockZ) && !isDwarf))
+        if (this.noPhysics) return false;
+        final boolean isShort = this.isDwarf || this.isSneaking();
+        final int blockX = MathHelper.floor(x);
+        final int blockY = MathHelper.floor(y);
+        final int blockZ = MathHelper.floor(z);
+        final double dX = x - (double)blockX;
+        final double dZ = z - (double)blockZ;
+        if(doesBlockPushOut(blockX, blockY, blockZ) || (doesBlockPushOut(blockX, blockY + 1, blockZ) && !isShort))
         {
-            boolean flag = !isBlockTranslucent(blockX - 1, blockY, blockZ) && !isBlockTranslucent(blockX - 1, blockY + 1, blockZ);
-            boolean flag1 = !isBlockTranslucent(blockX + 1, blockY, blockZ) && !isBlockTranslucent(blockX + 1, blockY + 1, blockZ);
-            boolean flag2 = !isBlockTranslucent(blockX, blockY, blockZ - 1) && !isBlockTranslucent(blockX, blockY + 1, blockZ - 1);
-            boolean flag3 = !isBlockTranslucent(blockX, blockY, blockZ + 1) && !isBlockTranslucent(blockX, blockY + 1, blockZ + 1);
-            byte byte0 = -1;
-            double d5 = 9999D;
-            if(flag && d3 < d5)
-            {
-                d5 = d3;
-                byte0 = 0;
-            }
-            if(flag1 && 1.0D - d3 < d5)
-            {
-                d5 = 1.0D - d3;
-                byte0 = 1;
-            }
-            if(flag2 && d4 < d5)
-            {
-                d5 = d4;
-                byte0 = 4;
-            }
-            if(flag3 && 1.0D - d4 < d5)
-            {
-                double d6 = 1.0D - d4;
-                byte0 = 5;
-            }
-            float f = 0.1F;
-            if(byte0 == 0)
+            final boolean flagWest = !doesBlockPushOut(blockX - 1, blockY, blockZ) && (isShort || !doesBlockPushOut(blockX - 1, blockY + 1, blockZ));
+            final boolean flagEast = !doesBlockPushOut(blockX + 1, blockY, blockZ) && (isShort || !doesBlockPushOut(blockX + 1, blockY + 1, blockZ));
+            final boolean flagNorth = !doesBlockPushOut(blockX, blockY, blockZ - 1) && (isShort || !doesBlockPushOut(blockX, blockY + 1, blockZ - 1));
+            final boolean flagSouth = !doesBlockPushOut(blockX, blockY, blockZ + 1) && (isShort || !doesBlockPushOut(blockX, blockY + 1, blockZ + 1));
+            Direction pushDirection = Direction.NONE;
+            double minLength = Double.MAX_VALUE;
+            if(flagWest && dX < minLength)
             {
-                xd = -f;
+                minLength = dX;
+                pushDirection = Direction.WEST;
             }
-            if(byte0 == 1)
+            if(flagEast && 1.0D - dX < minLength)
             {
-                xd = f;
+                minLength = 1.0D - dX;
+                pushDirection = Direction.EAST;
             }
-            if(byte0 == 4)
+            if(flagNorth && dZ < minLength)
             {
-                zd = -f;
+                minLength = dZ;
+                pushDirection = Direction.NORTH;
             }
-            if(byte0 == 5)
+            if(flagSouth && 1.0D - dZ < minLength)
             {
-                zd = f;
+//                minLength = 1.0D - dZ;
+                pushDirection = Direction.SOUTH;
             }
+            final float pushStrength = 0.1F;
+            this.xd = pushDirection.getOffsetX() * pushStrength;
+            this.zd = pushDirection.getOffsetZ() * pushStrength;
+            return true;
         }
         return false;
     }
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 73a8e8ae9..b9d846ee7 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
@@ -26,7 +26,6 @@ public class PlayerRemote extends Player
 //        fallTime = 0.0F;
         this.username = username;
         this.uuid = uuid;
-        heightOffset = 0.0F;
         footSize = 0.0F;
         noPhysics = true;
         sleepOffY = 0.25F;
@@ -35,12 +34,6 @@ public class PlayerRemote extends Player
         new GetSkinUrlThread(this);
     }
 
-    @Override
-	protected void resetHeight()
-    {
-        heightOffset = 0.0F;
-    }
-
     @Override
     public boolean hurt(Entity attacker, int i, DamageType type)
     {
@@ -153,10 +146,4 @@ public class PlayerRemote extends Player
 	public void sendStatusMessage(String message) {
 		
 	}
-
-    @Override
-    public float getHeadHeight()
-    {
-        return getHeightOffset();
-    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/Screen.java b/game/client/src/main/java/net/minecraft/client/gui/Screen.java
index 76015a8f2..c31c7044d 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/Screen.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/Screen.java
@@ -14,13 +14,14 @@ import net.minecraft.client.util.debug.DebugRender;
 import net.minecraft.client.input.InputType;
 
 import net.minecraft.core.sound.SoundCategory;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.GL11;
 
 public abstract class Screen extends Gui {
-    public Minecraft mc;
+    public final @NotNull Minecraft mc = Minecraft.getMinecraft();
     public int width;
     public int height;
     public List<ButtonElement> buttons;
@@ -106,8 +107,7 @@ public abstract class Screen extends Gui {
     protected void buttonReleased(ButtonElement button) {
     }
 
-    public void opened(Minecraft mc, int width, int height) {
-        this.mc = mc;
+    public void opened(int width, int height) {
         fontRenderer = mc.font;
         this.width = width;
         this.height = height;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenConnecting.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenConnecting.java
index 9d28afb55..bd490ad0c 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenConnecting.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenConnecting.java
@@ -15,7 +15,6 @@ public class ScreenConnecting extends Screen
     private static final Logger LOGGER = LogUtils.getLogger();
     public ScreenConnecting(Minecraft minecraft, String hostName, int port)
     {
-        mc = minecraft;
         cancelled = false;
         LOGGER.info("Connecting to {}, {}", hostName, port);
         minecraft.changeWorld(null);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/TextFieldElement.java b/game/client/src/main/java/net/minecraft/client/gui/TextFieldElement.java
index 3010e37cb..9bceeabe6 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/TextFieldElement.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/TextFieldElement.java
@@ -7,6 +7,7 @@ import net.minecraft.client.input.InputType;
 import net.minecraft.client.render.font.FontRenderer;
 import net.minecraft.client.render.window.CursorShape;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.input.Keyboard;
 
 import net.minecraft.client.gui.text.ITextField;
@@ -24,13 +25,13 @@ public class TextFieldElement extends Gui implements ITextField
     private int cursorCounter;
     public boolean isFocused;
     public boolean isEnabled;
-    public Screen parent;
+    public @Nullable Screen parent;
 	private ITextChangeListener textChangeListener;
     private String placeholder;
     public boolean drawBackground = true;
     private TextFieldEditor editor;
 
-    public TextFieldElement(Screen parent, FontRenderer fontRenderer, int xPosition, int yPosition, int width, int height, String defaultText, String placeholder)
+    public TextFieldElement(@Nullable Screen parent, FontRenderer fontRenderer, int xPosition, int yPosition, int width, int height, String defaultText, String placeholder)
     {
         isFocused = false;
         isEnabled = true;
@@ -92,8 +93,8 @@ public class TextFieldElement extends Gui implements ITextField
     public void mouseClicked(int x, int y, int mouseButton)
     {
         boolean hovered = isHovered(x, y);
-        if (((Minecraft.getMinecraft().inputType == InputType.CONTROLLER || Minecraft.getMinecraft().gameSettings.forceOnscreenKeyboard.value) && hovered && mouseButton == 0)) {
-            parent.mc.displayScreen(new ScreenKeyboard(parent, editor, s -> {}, (c, k, workingString) -> {}, s -> {}));
+        if (parent != null && ((Minecraft.getMinecraft().inputType == InputType.CONTROLLER || Minecraft.getMinecraft().gameSettings.forceOnscreenKeyboard.value) && hovered && mouseButton == 0)) {
+            this.parent.mc.displayScreen(new ScreenKeyboard(parent, editor, s -> {}, (c, k, workingString) -> {}, s -> {}));
         } else {
             setFocused(hovered);
             if(hovered && mouseButton == 1) {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/achievements/ScreenAchievements.java b/game/client/src/main/java/net/minecraft/client/gui/achievements/ScreenAchievements.java
index 8fa77fe57..e0eeb60bc 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/achievements/ScreenAchievements.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/achievements/ScreenAchievements.java
@@ -112,7 +112,6 @@ public class ScreenAchievements extends Screen
         this.statsCounter = statsCounter;
 
         this.parent = parent;
-        this.mc = Minecraft.getMinecraft();
         this.tooltip = new TooltipElement(mc);
         this.renderItem = new ItemElement(mc);
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/keyboard/ScreenKeyboard.java b/game/client/src/main/java/net/minecraft/client/gui/keyboard/ScreenKeyboard.java
index 9293a7038..7001f0262 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/keyboard/ScreenKeyboard.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/keyboard/ScreenKeyboard.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.gui.keyboard;
 
-import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.ControllerGlyphElement;
 import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.keyboard.keys.Key;
@@ -57,16 +56,15 @@ public class ScreenKeyboard extends Screen implements ITextField {
     }
 
     @Override
-    public void opened(Minecraft mc, int width, int height) {
+    public void opened(int width, int height) {
         Keyboard.enableRepeatEvents(true);
         if (parent != null) {
-            parent.mc = mc;
             parent.fontRenderer = mc.font;
             parent.width = width;
             parent.height = height;
         }
         this.glyphRenderer = new ControllerGlyphElement(mc);
-        super.opened(mc, width, height);
+        super.opened(width, height);
     }
 
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
index af3dc606f..449753dac 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
@@ -79,7 +79,6 @@ public class ScreenModelViewer extends ScreenPhotoMode implements ListenerTextFi
     protected boolean tickProgress = true;
     protected boolean rotateToCamera = true;
     public ScreenModelViewer(){
-        this.mc = Minecraft.getMinecraft();
         mc.currentWorld.loadedEntityList.clear();
         mc.currentWorld.loadedTileEntityList.clear();
         mc.thePlayer.absMoveTo(0.5, 64.5, 0.5, 180, 0);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/SearchFieldComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/SearchFieldComponent.java
index 748edd253..79f87af63 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/SearchFieldComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/SearchFieldComponent.java
@@ -29,7 +29,7 @@ public class SearchFieldComponent
     private ButtonElement clearButton;
 
     public SearchFieldComponent() {
-        textField = new TextFieldElement(null, mc.font, 0, 0, 150, 18, "", "Search...");
+        textField = new TextFieldElement(mc.currentScreen, mc.font, 0, 0, 150, 18, "", "Search...");
         textField.setMaxStringLength(20);
         textField.setTextChangeListener(this);
         editor = new TextFieldEditor(textField);
@@ -37,6 +37,12 @@ public class SearchFieldComponent
             .setTextures("minecraft:gui/screen/options/clear", "minecraft:gui/screen/options/clear_highlighted", null);
     }
 
+    @Override
+    public void init(final Minecraft mc) {
+        OptionsComponent.super.init(mc);
+        textField.parent = mc.currentScreen;
+    }
+
     @Override
     public void tick() {
         textField.updateCursorCounter();
diff --git a/game/client/src/main/java/net/minecraft/client/gui/popup/TextInputComponent.java b/game/client/src/main/java/net/minecraft/client/gui/popup/TextInputComponent.java
index 82aa528a4..60a0a693c 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/popup/TextInputComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/popup/TextInputComponent.java
@@ -11,7 +11,7 @@ public class TextInputComponent
     public TextInputComponent(int width, String defaultText, String placeholder)
     {
         super(width);
-        this.textField = new TextFieldElement(null, Minecraft.getMinecraft().font, 0, 0, width, getHeight(), defaultText, placeholder);
+        this.textField = new TextFieldElement(Minecraft.getMinecraft().currentScreen, Minecraft.getMinecraft().font, 0, 0, width, getHeight(), defaultText, placeholder);
     }
 
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/input/PlayerInput.java b/game/client/src/main/java/net/minecraft/client/input/PlayerInput.java
index 322792f2b..0a6c4cea0 100644
--- a/game/client/src/main/java/net/minecraft/client/input/PlayerInput.java
+++ b/game/client/src/main/java/net/minecraft/client/input/PlayerInput.java
@@ -113,7 +113,7 @@ public class PlayerInput {
 		moveForward = MathHelper.clamp(moveForward, -1, 1);
 		moveStrafe = MathHelper.clamp(moveStrafe, -1, 1);
 
-		if(sneak && !entityplayer.noPhysics) {
+		if(entityplayer.isSneaking() && !entityplayer.noPhysics) {
 			moveStrafe *= 0.3;
 			moveForward *= 0.3;
 		}
diff --git a/game/client/src/main/java/net/minecraft/client/option/GameSettings.java b/game/client/src/main/java/net/minecraft/client/option/GameSettings.java
index 3fc6bdc94..2761fd304 100644
--- a/game/client/src/main/java/net/minecraft/client/option/GameSettings.java
+++ b/game/client/src/main/java/net/minecraft/client/option/GameSettings.java
@@ -18,7 +18,6 @@ import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.hud.component.HudComponents;
 import net.minecraft.client.input.InputDevice;
 import net.minecraft.client.option.enums.Colorblindness;
-import net.minecraft.client.render.font.Font;
 import net.minecraft.client.render.font.Fonts;
 import net.minecraft.core.enums.ChatVisibility;
 import net.minecraft.core.enums.Difficulty;
@@ -484,7 +483,7 @@ public class GameSettings {
 			guiScale.value = (guiScale.value + max) % max;
 			mc.resolution.setScale(guiScale.value);
 			if (mc.currentScreen != null) {
-				mc.currentScreen.opened(mc, mc.resolution.getScaledWidthScreenCoords(), mc.resolution.getScaledHeightScreenCoords());
+				mc.currentScreen.opened(mc.resolution.getScaledWidthScreenCoords(), mc.resolution.getScaledHeightScreenCoords());
 			}
 		}
 		if(option == mipmapType || option == mipmapLevels) {
@@ -504,7 +503,7 @@ public class GameSettings {
 		}
 		if(option == language) {
 			if (mc.currentScreen != null) {
-				mc.currentScreen.opened(mc, mc.resolution.getScaledWidthScreenCoords(), mc.resolution.getScaledHeightScreenCoords());
+				mc.currentScreen.opened(mc.resolution.getScaledWidthScreenCoords(), mc.resolution.getScaledHeightScreenCoords());
 			}
 		}
 		if(option == lightmapStyle) {
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 0a4e137ed..319fce2b6 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
@@ -1423,7 +1423,7 @@ public class RenderGlobal
             }
             else if (hitResult.hitType == HitResult.HitType.ENTITY && hitResult.entity.showBoundingBoxOnHover() && !mc.gameSettings.showCollisionBoxes.value)
             {
-                drawInterpolatedEntityBoundingBox(hitResult.entity, camera, partialTick);
+                drawInterpolatedEntityBoundingBox(hitResult.entity, hitResult.entity.bb, camera, partialTick);
             }
 
             GL11.glDepthMask(true);
@@ -1450,16 +1450,50 @@ public class RenderGlobal
 		if(mc.thePlayer.getGamemode() == Gamemode.creative) {
 			entityRadius = 100.0f;
 		}
-        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-		List<Entity> entitiesNearby = worldObj.getEntitiesWithinAABBExcludingEntity(mc.thePlayer, mc.thePlayer.bb.grow(entityRadius, entityRadius, entityRadius));
-		for (Entity e : entitiesNearby) {
-			drawInterpolatedEntityBoundingBox(e, camera, partialTicks);
-		}
+		List<Entity> entitiesNearby = worldObj.getEntitiesWithinAABBExcludingEntity(null, mc.thePlayer.bb.grow(entityRadius, entityRadius, entityRadius));
+        for (Entity e : entitiesNearby) {
+            glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+            drawInterpolatedEntityBoundingBox(e, e.bb, camera, partialTicks); // Bounds
+
+            glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
+            final AABB head = e.bb.copy();
+            head.set(head.minX, e.y + e.getHeadHeight() - 0.005, head.minZ, head.maxX, e.y + e.getHeadHeight() + 0.005, head.maxZ);
+            drawInterpolatedEntityBoundingBox(e, head, camera, partialTicks); // Head
+
+            glColor4f(1.0f, 0.0f, 1.0f, 1.0f);
+            final AABB feet = AABB.getTemporaryBB(e.bb.minX, e.y - 0.005, e.bb.minZ, e.bb.maxX, e.y + 0.005, e.bb.maxZ);
+            drawInterpolatedEntityBoundingBox(e, feet, camera, partialTicks); // Feet
+
+            glColor4f(0.75f, 0.75f, 1.0f, 1.0f);
+            drawInterpolatedEntityBoundingBox(e, EntityRenderDispatcher.instance.getRenderer(e).entityViewBox(e), camera, partialTicks); // Model vis bounds
+
+            double lerpOffsetX = MathHelper.lerp(e.xo, e.x, partialTicks) - camera.getX(partialTicks);
+            double lerpOffsetY = MathHelper.lerp(e.yo, e.y, partialTicks) - camera.getY(partialTicks);
+            double lerpOffsetZ = MathHelper.lerp(e.zo, e.z, partialTicks) - camera.getZ(partialTicks);
+            drawDebugVec(Tessellator.instance, Vec3.getTempVec3(lerpOffsetX, lerpOffsetY + e.getHeadHeight(), lerpOffsetZ), e.getViewVector(partialTicks), 1, 0, 1, 0, 1);
+            glDisable(GL_TEXTURE_2D);
+            GL11.glLineWidth(2);
+        }
 		
 		glEnable(GL_TEXTURE_2D);
 	}
+
+    public static void drawDebugVec(final Tessellator tessellator, final Vec3 pos, final Vec3 vec, final double scale, final float r, final float g, final float b, final float a){
+        if (pos == null || vec == null) return;
+        GL11.glLineWidth(10);
+        GL11.glDisable(GL11.GL_TEXTURE_2D);
+        tessellator.startDrawing(GL11.GL_LINES);
+        tessellator.setColorRGBA_F(r, g, b, a);
+        tessellator.addVertex(pos.x, pos.y, pos.z);
+        tessellator.addVertex(
+            pos.x + vec.x * scale,
+            pos.y + vec.y * scale,
+            pos.z + vec.z * scale);
+        tessellator.draw();
+        GL11.glEnable(GL11.GL_TEXTURE_2D);
+    }
     
-    public void drawInterpolatedEntityBoundingBox(Entity entity, ICamera camera, float partialTicks) {
+    public void drawInterpolatedEntityBoundingBox(Entity entity, AABB boundingBox, ICamera camera, float partialTicks) {
         double cameraX = camera.getX(partialTicks);
         double cameraY = camera.getY(partialTicks);
         double cameraZ = camera.getZ(partialTicks);
@@ -1467,7 +1501,6 @@ public class RenderGlobal
         double lerpOffsetX = entity.xo + (entity.x - entity.xo) * partialTicks;
         double lerpOffsetY = entity.yo + (entity.y - entity.yo) * partialTicks;
         double lerpOffsetZ = entity.zo + (entity.z - entity.zo) * partialTicks;
-        AABB boundingBox = entity.bb;
         boundingBox = boundingBox.grow(expand, expand, expand);
         boundingBox = boundingBox.cloneMove(-entity.x, -entity.y, -entity.z);
         boundingBox = boundingBox.cloneMove(-cameraX, -cameraY, -cameraZ);
diff --git a/game/client/src/main/java/net/minecraft/client/render/TextureManager.java b/game/client/src/main/java/net/minecraft/client/render/TextureManager.java
index 22f510e6c..47fca8990 100644
--- a/game/client/src/main/java/net/minecraft/client/render/TextureManager.java
+++ b/game/client/src/main/java/net/minecraft/client/render/TextureManager.java
@@ -68,7 +68,7 @@ public class TextureManager {
 	public final Map<String, Texture> textureMap = new HashMap<>();
 	public final List<TextureBuffered> bufferedTextures = new ArrayList<>();
 	public final Map<String, TextureDownloaded> downloadedTextures = new HashMap<>();
-	public final Map<NamespaceID, DynamicTexture> dynamicTextures = new HashMap<>();
+	public final Map<String, DynamicTexture> dynamicTextures = new HashMap<>();
 	
 	private final GameSettings gameSettings;
 	public TexturePackList texturePacks;
@@ -139,7 +139,7 @@ public class TextureManager {
 	}
 	protected void addDynamicTextureOverride(DynamicTexture texture, boolean override) {
 		if (!override && dynamicTextures.containsKey(texture.targetTexture.namespaceId)) return;
-		dynamicTextures.put(texture.targetTexture.namespaceId, texture);
+		dynamicTextures.put(texture.targetTexture.namespaceId.namespace + ":" + TextureRegistry.stitcherMapReverse.get(texture.targetTexture.parentAtlas) + "/" + texture.targetTexture.namespaceId.value, texture);
 	}
 
 	private void loadCustomAnimations() {
diff --git a/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java b/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
index bd0410481..fb9713e93 100644
--- a/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
@@ -131,17 +131,18 @@ public class WorldRenderer
 		final double blockReach = mc.playerController.getBlockReachDistance();
 		final double entityReach = mc.playerController.getEntityReachDistance();
 		
-		Vec3 pos1 = mc.thePlayer.getPosition(partialTicks, false);
+		Vec3 pos1 = mc.thePlayer.getPosition(partialTicks, true);
 		Vec3 look = mc.thePlayer.getViewVector(partialTicks);
 		Vec3 pos2 = pos1.add(look.x * blockReach, look.y * blockReach, look.z * blockReach);
 		
 		// Raytrace blocks
-		mc.objectMouseOver = mc.currentWorld.checkBlockCollisionBetweenPoints(pos1, pos2, false, false, true);
-		
+		mc.objectMouseOver = mc.thePlayer.rayTrace(blockReach, partialTicks, false, false, true);
+//		mc.objectMouseOver = mc.currentWorld.checkBlockCollisionBetweenPoints(pos1, pos2, false, false, true);
+
 		// Calculate again because block raytrace changes the values
-		pos1 = mc.thePlayer.getPosition(partialTicks, false);
-		look = mc.thePlayer.getViewVector(partialTicks);
-		pos2 = pos1.add(look.x * entityReach, look.y * entityReach, look.z * entityReach);
+//		pos1 = mc.thePlayer.getPosition(partialTicks, false);
+//		look = mc.thePlayer.getViewVector(partialTicks);
+//		pos2 = pos1.add(look.x * entityReach, look.y * entityReach, look.z * entityReach);
 		
 		double hitBlockDistance = 1000.0;
 		if(mc.objectMouseOver != null) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/camera/EntityCamera.java b/game/client/src/main/java/net/minecraft/client/render/camera/EntityCamera.java
index fea78b848..744028fb8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/camera/EntityCamera.java
+++ b/game/client/src/main/java/net/minecraft/client/render/camera/EntityCamera.java
@@ -3,6 +3,7 @@ package net.minecraft.client.render.camera;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.culling.CameraFrustum;
 import net.minecraft.core.entity.Mob;
+import net.minecraft.core.util.helper.MathHelper;
 
 public abstract class EntityCamera
     implements ICamera
@@ -13,6 +14,8 @@ public abstract class EntityCamera
 
     public final Mob mob;
 
+    private double hhO = Double.NaN;
+
     public EntityCamera(Minecraft mc, Mob mob)
     {
         this.mc = mc;
@@ -27,7 +30,9 @@ public abstract class EntityCamera
     }
 
     @Override
-    public void tick() { }
+    public void tick() {
+        this.hhO = this.mob.getHeadHeight();
+    }
 
     @Override
     public void applyGlTransformations() { }
@@ -50,11 +55,12 @@ public abstract class EntityCamera
     {
         if (partialTick == 1f)
         {
-            return mob.y;
+            return mob.y + mob.getHeadHeight();
         }
         else
         {
-            return (mob.yo + (mob.y - mob.yo) * partialTick);
+            if (Double.isNaN(this.hhO)) this.hhO = this.mob.getHeadHeight();
+            return (this.mob.yo + (this.mob.y - this.mob.yo) * partialTick) + MathHelper.lerp(this.hhO, this.mob.getHeadHeight(), partialTick);
         }
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBiped.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBiped.java
index c881e28bb..70d67c023 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBiped.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBiped.java
@@ -114,6 +114,7 @@ public abstract class MobRendererBiped<T extends Mob> extends MobRenderer<T> {
 
         if(entity.isSneaking())
         {
+            waist.posY -= 4;
             leftLeg.posZ += 5;
             rightLeg.posZ += 5;
             head.posY -= 2;
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 5c5ae9313..f9accee20 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
@@ -21,6 +21,7 @@ import net.minecraft.core.world.BlocksContainer;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.models.entity.BoneTransform;
 import org.useless.dragonfly.models.entity.StaticEntityModel;
 
 public class MobRendererPlayer extends MobRendererBipedArmored<Player>
@@ -172,8 +173,7 @@ public class MobRendererPlayer extends MobRendererBipedArmored<Player>
 
     @Override
     protected void preRenderTransform(@NotNull final Player entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
-        GL11.glTranslated(x, y - entity.getHeightOffset() + entity.getHeadHeight(), z); // TODO the fact that the offset for players is so fucking dumb really needs to be fixed at some point
-
+        GL11.glTranslated(x, y, z);
 
         if(entity.isAlive() && (entity.isPlayerSleeping())) {
             GL11.glTranslatef(entity.sleepOffX, entity.sleepOffY, entity.sleepOffZ);
@@ -233,7 +233,7 @@ public class MobRendererPlayer extends MobRendererBipedArmored<Player>
                 final float bodyAngle = 5;
                 final double xd = MathHelper.lerp(player.xdO, player.xd, partialTick);
                 final double yd = Math.min(MathHelper.lerp(player.ydO, player.yd, partialTick), 0);
-                final double zd = MathHelper.lerp(player.zd0, player.zd, partialTick);
+                final double zd = MathHelper.lerp(player.zdO, player.zd, partialTick);
                 final double vel = -1/(3 * Math.hypot(xd, zd) + 1) + 1;
                 final double moveAng = Math.atan2(xd, zd);
                 final double yawRad = Math.toRadians(yawOff);
@@ -288,6 +288,10 @@ public class MobRendererPlayer extends MobRendererBipedArmored<Player>
             model1.getTransform("leftPant").visible = entity.playerConfig.pantLeftEnabled();
             model1.getTransform("rightPant").visible = entity.playerConfig.pantRightEnabled();
         }
+        if (entity.isDwarf() && entity.isSneaking()) {
+            final BoneTransform waist = model.getTransform("waist");
+            waist.posY -= 4;
+        }
         return model1;
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSpider.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSpider.java
index 64a370322..27c354d3b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSpider.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSpider.java
@@ -24,6 +24,10 @@ public class MobRendererSpider extends MobRenderer<MobSpider> {
             GL11.glDisable(GL11.GL_ALPHA_TEST);
             GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
             GL11.glColor4f(1.0F, 1.0F, 1.0F, (1.0F - entity.getBrightness(partialTick)) * 0.5F);
+        } else if (layer == 2) {
+            GL11.glDisable(GL11.GL_BLEND);
+            GL11.glEnable(GL11.GL_ALPHA_TEST);
+            return null;
         }
 
         final StaticEntityModel model = getModel("main");
@@ -101,6 +105,6 @@ public class MobRendererSpider extends MobRenderer<MobSpider> {
 
     @Override
     protected int maxRenderLayer(@NotNull final MobSpider entity) {
-        return 1;
+        return 2;
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java b/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java
index 442f0444d..a50d1c083 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java
@@ -37,7 +37,7 @@ import java.util.stream.Stream;
 public class TextureRegistry {
     private static final Logger LOGGER = LogUtils.getLogger();
     public static HashMap<String, AtlasStitcher> stitcherMap = new HashMap<>();
-    protected static HashMap<AtlasStitcher, String> stitcherMapReverse = new HashMap<>();
+    public static HashMap<AtlasStitcher, String> stitcherMapReverse = new HashMap<>();
     @SuppressWarnings("unused")
     public static AtlasStitcher blockAtlas = register("block", new AtlasStitcher("textures/block", false, true, "/assets/minecraft/textures/block/texture_missing.png"));
     @SuppressWarnings("unused")
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesBase.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesBase.java
index 909c71149..df990ed28 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesBase.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLeavesBase.java
@@ -39,9 +39,7 @@ public class BlockLogicLeavesBase extends BlockLogic
     @Override
     public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int meta, TileEntity tileEntity)
     {
-
-        Season season = world.getSeasonManager().getCurrentSeason();
-        float dropRate = season != null ? 20 / season.saplingDropFactor : 20;
+        float dropRate = 20;
         if (dropCause == EnumDropCause.PICK_BLOCK || dropCause == EnumDropCause.SILK_TOUCH) return new ItemStack[] { new ItemStack(block) };
 
         int numDropped = 1;
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 d04a9eb6d..9f948e462 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
@@ -157,10 +157,6 @@ public abstract class Entity
 
     protected void resetPos()
     {
-        if(world == null)
-        {
-            return;
-        }
         do
         {
             if(y <= 0.0D)
@@ -200,20 +196,24 @@ public abstract class Entity
         this.xRot = xRot % 360F;
     }
 
-    public void setPos(double x, double y, double z)
+    public void setPos(final double x, final double y, final double z)
     {
         this.x = x;
         this.y = y;
         this.z = z;
-        float center = bbWidth / 2.0F;
-        float heightOfMob = bbHeight;
-        bb.set(
-                x - (double)center,
-                (y - (double) heightOffset) + (double) ySlideOffset,
-                z - (double)center,
-                x + (double)center,
-                (y - (double) heightOffset) + (double) ySlideOffset + (double)heightOfMob,
-                z + (double)center);
+        setBounds();
+    }
+
+    public void setBounds() {
+        final double center = this.bbWidth / 2.0d;
+        final double heightOfMob = this.bbHeight;
+        this.bb.set(
+            x - center,
+            (y - (double) this.heightOffset) + (double) this.ySlideOffset,
+            z - center,
+            x + center,
+            (y - (double) this.heightOffset) + (double) this.ySlideOffset + heightOfMob,
+            z + center);
     }
 
     public void interpolateTurn(float yRot, float xRot)
@@ -241,10 +241,6 @@ public abstract class Entity
 
     public void baseTick()
     {
-        if (world == null) {
-            return;
-        }
-
         pushesThisTick = 0;
         pushTime *= 0.98f;
         if (pushTime < 0.001f){
@@ -334,9 +330,6 @@ public abstract class Entity
         firstTick = false;
     }
     protected void checkOnWater(boolean addVelocity) {
-        if (world == null) {
-            return;
-        }
         if (checkAndHandleWater(addVelocity))
         {
             if(!wasInWater && !firstTick)
@@ -414,9 +407,6 @@ public abstract class Entity
 
     public boolean isFree(double x, double y, double z)
     {
-        if (world == null) {
-            return true;
-        }
         AABB offsetBb = bb.cloneMove(x, y, z).grow(-0.01, -0.01, -0.01);
         List<AABB> list = world.getCubes(this, offsetBb);
         if(!list.isEmpty())
@@ -428,7 +418,7 @@ public abstract class Entity
 
     public void move(double xd, double yd, double zd)
     {
-        if(noPhysics || world == null)
+        if(noPhysics)
         {
         	onGround = false;
             bb.move(xd, yd, zd);
@@ -456,7 +446,7 @@ public abstract class Entity
         AABB bbCopy = bb.copy();
         
         double bbWidth = bb.maxX - bb.minX - 0.05;
-        if(isSneaking()) {
+        if(isSneaking()) { // Edge safety behavior
 			if(xd != 0.0) {
 				AABB floor = AABB.getTemporaryBB(bb.minX, bb.minY - 1.0, bb.minZ, bb.maxX, bb.minY, bb.maxZ).expand(xd, 0.0, 0.0);
 				List<AABB> collidingBoxes = world.getCubes(this, floor);
@@ -784,9 +774,6 @@ public abstract class Entity
 
     public boolean isInWaterOrRain()
     {
-        if (world == null) {
-            return false;
-        }
         return wasInWater || world.canBlockBeRainedOn(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z));
     }
 
@@ -797,17 +784,11 @@ public abstract class Entity
 
     public boolean checkAndHandleWater(boolean addVelocity)
     {
-        if (world == null) {
-            return false;
-        }
         return world.handleMaterialAcceleration(bb/*.expand(0.0D, -0.4D, 0.0D)*/.getInsetBoundingBox(0.001D, 0.001D, 0.001D), Material.water, this, addVelocity);
     }
 
     public boolean isUnderLiquid(Material material)
     {
-        if (world == null) {
-            return false;
-        }
         double d = y + (double) getHeadHeight();
         int i = MathHelper.floor(x);
         int j = MathHelper.floor_float(MathHelper.floor(d));
@@ -832,9 +813,6 @@ public abstract class Entity
 
     public boolean isInLava()
     {
-        if (world == null) {
-            return false;
-        }
         return world.isMaterialInBB(bb/*.expand(-0.1D, -0.4D, -0.1D)*/, Material.lava);
     }
 
@@ -883,13 +861,7 @@ public abstract class Entity
     }
     
     public int getLightmapCoord(float partialTick) {
-    	if(world == null) {
-    		// Happens when the guidebook is rendered
-//    		return LightmapHelper.getLightmapCoord(15, 15);
-            return 0xFFFFFFFF; // TODO make this work properly when world is null
-    	}
-    	
-    	int blockX = MathHelper.floor(x);
+        int blockX = MathHelper.floor(x);
         double d = (bb.maxY - bb.minY) * 0.66D;
     	int blockY = MathHelper.floor((y - (double) heightOffset) + d);
     	int blockZ = MathHelper.floor(z);
@@ -1196,9 +1168,6 @@ public abstract class Entity
 
     public boolean isInWall()
     {
-        if (world == null) {
-            return false;
-        }
         for(int i = 0; i < 8; i++)
         {
             float f = ((float)((i >> 0) % 2) - 0.5F) * bbWidth * 0.9F;
@@ -1343,7 +1312,7 @@ public abstract class Entity
         return 0.1F;
     }
 
-    public Vec3 getLookAngle()
+    public Vec3 getViewVector(float partialTick)
     {
         return null;
     }
@@ -1439,9 +1408,6 @@ public abstract class Entity
 
     protected boolean checkInTile(double d, double d1, double d2)
     {
-        if (world == null) {
-            return false;
-        }
         int i = MathHelper.floor(d);
         int j = MathHelper.floor(d1);
         int k = MathHelper.floor(d2);
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 a67b4fb3e..7ac1d3fdd 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
@@ -254,9 +254,6 @@ public abstract class Mob extends Entity
 
     public void playLivingSound()
     {
-        if (world == null) {
-            return;
-        }
         String s = getLivingSound();
         if(s != null && !world.isClientSide)
         {
@@ -266,17 +263,11 @@ public abstract class Mob extends Entity
     
     public void playHurtSound()
     {
-        if (world == null) {
-            return;
-        }
         world.playSoundAtEntity(null, this, getHurtSound(), getSoundVolume(), (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F);
     }
     
     public void playDeathSound()
     {
-        if (world == null) {
-            return;
-        }
         world.playSoundAtEntity(null, this, getDeathSound(), getSoundVolume(), (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F);
     }
 
@@ -285,9 +276,6 @@ public abstract class Mob extends Entity
     {
         prevSwingProgress = swingProgress;
         super.baseTick();
-        if (world == null) {
-            return;
-        }
         if(random.nextInt(1000) < livingSoundTime++)
         {
             livingSoundTime = -getAmbientSoundInterval();
@@ -349,9 +337,6 @@ public abstract class Mob extends Entity
     }
 
     public void trySuffocate(){
-        if (world == null) {
-            return;
-        }
         if(isAlive() && isUnderLiquid(Material.water) && !canBreatheUnderwater())
         {
             airSupply--;
@@ -377,9 +362,6 @@ public abstract class Mob extends Entity
 
     public void spawnExplosionParticle()
     {
-        if (world == null) {
-            return;
-        }
         for(int i = 0; i < 20; i++)
         {
             double d = random.nextGaussian() * 0.02D;
@@ -474,12 +456,6 @@ public abstract class Mob extends Entity
         unusedRotation1 += f2;
     }
 
-    @Override
-	protected void setSize(float width, float height)
-    {
-        super.setSize(width, height);
-    }
-
     public void heal(int i)
     {
         if(getHealth() <= 0)
@@ -979,9 +955,6 @@ public abstract class Mob extends Entity
 
     public void onLivingUpdate()
     {
-        if (world == null) {
-            return;
-        }
         if(newPosRotationIncrements > 0)
         {
             double d = x + (newPosX - x) / (double)newPosRotationIncrements;
@@ -1249,12 +1222,7 @@ public abstract class Mob extends Entity
     }
 
     @Override
-	public Vec3 getLookAngle()
-    {
-        return getViewVector(1.0F);
-    }
-
-    public Vec3 getViewVector(float partialTick)
+	public Vec3 getViewVector(float partialTick)
     {
         if(partialTick == 1.0F)
         {
@@ -1276,12 +1244,13 @@ public abstract class Mob extends Entity
         }
     }
 
-    public HitResult rayTrace(double distance, float partialTick, boolean collideWithFluids, boolean ignoreNonColliderBlocks)
+
+    public HitResult rayTrace(double distance, float partialTick, boolean collideWithFluids, boolean ignoreNonColliderBlocks, boolean useSelectorBoxes)
     {
         Vec3 head = getPosition(partialTick, true);
         Vec3 viewDirection = getViewVector(partialTick);
         Vec3 furthestPoint = head.add(viewDirection.x * distance, viewDirection.y * distance, viewDirection.z * distance);
-        return world.checkBlockCollisionBetweenPoints(head, furthestPoint, collideWithFluids, ignoreNonColliderBlocks, false);
+        return world.checkBlockCollisionBetweenPoints(head, furthestPoint, collideWithFluids, ignoreNonColliderBlocks, useSelectorBoxes);
     }
 
     public int getMaxSpawnedInChunk()
diff --git a/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java b/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java
index e041b0552..4418c052c 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java
@@ -33,9 +33,6 @@ public abstract class MobPathfinder extends Mob
     @Override
 	protected void updateAI()
     {
-        if (world == null) {
-            return;
-        }
         hasAttacked = isMovementCeased();
         float sightRadius = 16F;
         if(target == null)
@@ -148,9 +145,6 @@ public abstract class MobPathfinder extends Mob
     }
 
     protected @Nullable Entity getClosestFireflyToEntity (int x, int y, int z, float radius){
-        if (world == null) {
-            return null;
-        }
         List<MobFireflyCluster> nearbyFireflies = world.getEntitiesWithinAABB(MobFireflyCluster.class, AABB.getTemporaryBB(this.x, this.y, this.z, this.x + 1.0D, this.y + 1.0D, this.z + 1.0D).grow(radius, 4D, radius));
 
         double closestDistance = -1D;
@@ -170,9 +164,6 @@ public abstract class MobPathfinder extends Mob
 
     protected void roamRandomPath()
     {
-        if (world == null) {
-            return;
-        }
         boolean canMoveToPoint = false;
         int x = -1;
         int y = -1;
@@ -221,9 +212,6 @@ public abstract class MobPathfinder extends Mob
     @Override
 	public boolean canSpawnHere()
     {
-        if (world == null) {
-            return false;
-        }
         int x = MathHelper.floor(this.x);
         int y = MathHelper.floor(bb.minY);
         int z = MathHelper.floor(this.z);
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 d146f3144..677df77da 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
@@ -51,7 +51,6 @@ import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.player.inventory.container.ContainerInventory;
 import net.minecraft.core.player.inventory.menu.MenuAbstract;
 import net.minecraft.core.player.inventory.menu.MenuInventory;
-import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.DamageType;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.MathHelper;
@@ -74,6 +73,9 @@ public abstract class Player
     extends Mob
     implements IArmorWearing<HumanArmorShape>, IItemHolding
 {
+    public static final int MOTION_STATE_DEFAULT = 0;
+    public static final int MOTION_STATE_CROUCHED = 1;
+
     public static final int DATA_UNKNOWN = 16; // I have no idea wtf this id is for
     public static final int DATA_SELECTED_ART = 17;
     public static final int DATA_HELD_ARROW = 18;
@@ -94,8 +96,9 @@ public abstract class Player
     public int dimension;
     public double xdO;
     public double ydO;
-    public double zd0;
+    public double zdO;
     protected boolean sleeping;
+    protected boolean sneaking;
     public ChunkCoordinates bedChunkCoordinates;
     public ChunkCoordinates dimensionEnterCoordinate;
     private int sleepTimer;
@@ -139,7 +142,6 @@ public abstract class Player
         bobberEntity = null;
         inventorySlots = new MenuInventory(inventory, !world.isClientSide);
         craftingInventory = inventorySlots;
-        heightOffset = 1.62F;
         ChunkCoordinates chunkcoordinates = world.getSpawnPoint();
         moveTo((double)chunkcoordinates.x + 0.5D, chunkcoordinates.y + 1, (double)chunkcoordinates.z + 0.5D, 0.0F, 0.0F);
 //        rotOffs = 180F;
@@ -163,25 +165,30 @@ public abstract class Player
         entityData.set(DATA_SELECTED_ART, (byte)ArtType.values.indexOf(selectedArt));
     }
 
-    private void setupDwarfMode() {
-        boolean dwarfModeEnabled = world.getGameRuleValue(GameRules.DWARF_MODE);
-        if (dwarfModeEnabled && !isDwarf) {
-            setSize(0.6f, 1.0f - 0.2f);
-            heightOffset = 1.0F - 0.38F;
-            setPos(x, y - 1f, z);
-        } else if (!dwarfModeEnabled && isDwarf) {
-            setSize(0.6f, 2.0f - 0.2f);
-            heightOffset = 2.0f - 0.38F;
-            setPos(x, y + 1f, z);
+    private void setupScale() {
+        isDwarf = world.getGameRuleValue(GameRules.DWARF_MODE);
+        if (this.isDwarf) {
+            setSize(0.6f, isSneaking() ? 0.5f : 0.8f);
+        } else {
+            setSize(0.6f, isSneaking() ? 1.5f : 1.8f);
         }
-
-        isDwarf = dwarfModeEnabled;
+        setBounds();
     }
 
     public boolean isDwarf() {
         return isDwarf;
     }
 
+    @Override
+    public boolean isSneaking()
+    {
+        return this.sneaking;
+    }
+
+    protected boolean wantSneak() {
+        return getSharedFlag(FLAG_SNEAKING);
+    }
+
     @Override
 	protected void defineSynchedData()
     {
@@ -202,6 +209,43 @@ public abstract class Player
         }
     }
 
+    // Determines if a block pushes the player out of it
+    protected boolean doesBlockPushOut(int x, int y, int z)
+    {
+        return world.isBlockNormalCube(x, y, z);
+    }
+
+    protected boolean boundsClear(@NotNull final AABB bounds) {
+        return world.getCubes(this, bounds).isEmpty();
+    }
+
+    protected AABB getBoundsForState(final int state) {
+        final double center = this.bbWidth / 2.0d;
+        switch (state) {
+            case MOTION_STATE_CROUCHED: {
+                final double heightOfMob = isDwarf() ? 0.5 : 1.5f;
+                return AABB.getTemporaryBB(
+                    this.x - center,
+                    (this.y - (double) this.heightOffset) + (double) this.ySlideOffset,
+                    this.z - center,
+                    this.x + center,
+                    (this.y - (double) this.heightOffset) + (double) this.ySlideOffset + heightOfMob,
+                    this.z + center).shrink(0.0125, 0.0125, 0.0125);
+            }
+            case MOTION_STATE_DEFAULT:
+            default: {
+                final double heightOfMob = isDwarf() ? 0.8 : 1.8f;
+                return AABB.getTemporaryBB(
+                    this.x - center,
+                    (this.y - (double) this.heightOffset) + (double) this.ySlideOffset,
+                    this.z - center,
+                    this.x + center,
+                    (this.y - (double) this.heightOffset) + (double) this.ySlideOffset + heightOfMob,
+                    this.z + center).shrink(0.0125, 0.0125, 0.0125);
+            }
+        }
+    }
+
     @Override
 	public void tick()
     {
@@ -215,8 +259,22 @@ public abstract class Player
 
         xdO = xd;
         ydO = yd;
-        zd0 = zd;
-        setupDwarfMode();
+        zdO = zd;
+
+        final boolean wSneak = wantSneak();
+
+        if (wSneak) {
+            this.sneaking = true;
+        } else {
+            if (boundsClear(getBoundsForState(MOTION_STATE_DEFAULT))) {
+                this.sneaking = false;
+            } else if (boundsClear(getBoundsForState(MOTION_STATE_CROUCHED))) {
+                this.sneaking = true;
+            }
+        }
+
+
+        setupScale();
 
         if(isPlayerSleeping())
         {
@@ -293,12 +351,10 @@ public abstract class Player
     @Override
 	public void resetPos()
     {
-        heightOffset = 1.62F;
-        setSize(0.6F, 1.8F);
-        super.resetPos();
+        setupScale();
         setHealthRaw(getMaxHealth());
         deathTime = 0;
-        setupDwarfMode();
+        super.resetPos();
     }
 
     @Override
@@ -449,15 +505,9 @@ public abstract class Player
         {
             xd = zd = 0.0D;
         }
-        heightOffset = 0.1F;
         addStat(StatList.deathsStat, 1);
     }
 
-    @Override
-    public float getShadowHeightOffs() {
-        return super.getShadowHeightOffs() - getHeightOffset();
-    }
-
     @Override
     public boolean sendDeathMessage(Entity entityKilledBy){
         return true;
@@ -755,6 +805,7 @@ public abstract class Player
         sleepTimer = tag.getShort("SleepTimer");
         setGamemodeOnLogin(Gamemode.gamemodesList[tag.getInteger("Gamemode")]);
         noPhysics = tag.getBoolean("Noclip") && gamemode.canPlayerFly();
+        this.sneaking = tag.getBoolean("Sneaking");
         if(sleeping)
         {
             bedChunkCoordinates = new ChunkCoordinates(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z));
@@ -786,6 +837,7 @@ public abstract class Player
         tag.putShort("SleepTimer", (short)sleepTimer);
         tag.putInt("Gamemode", gamemode.getId());
         tag.putBoolean("Noclip", noPhysics && gamemode.canPlayerFly());
+        tag.putBoolean("Sneaking", this.sneaking);
         if(playerSpawnCoordinate != null)
         {
             tag.putInt("SpawnX", playerSpawnCoordinate.x);
@@ -844,24 +896,8 @@ public abstract class Player
     }
 
     @Override
-	public float getHeadHeight()
-    {
-        return 0;
-    }
-
-    protected void resetHeight()
-    {
-        heightOffset = getHeightOffset();
-    }
-    public float getHeightOffset(){
-        if (isDwarf)
-        {
-            return 1.0F - 0.38F;
-        }
-        else
-        {
-            return 2.0f - 0.38F;
-        }
+	public float getHeadHeight() {
+        return this.bbHeight - 0.18f;
     }
 
     public boolean killPlayer()
@@ -1065,7 +1101,7 @@ public abstract class Player
     }
 
     @Override
-	  public double getRidingHeight()
+    public double getRidingHeight()
     {
         return isDwarf ? heightOffset + 0.05 : heightOffset - 0.5f;
     }
@@ -1170,7 +1206,6 @@ public abstract class Player
     
     private void setPlayerSleeping(int x, int y, int z) {
         setSize(0.2F, 0.2F);
-        heightOffset = 0.2F;
         if(world.isBlockLoaded(x, y, z))
         {
             int meta = world.getBlockMetadata(x, y, z);
@@ -1229,8 +1264,7 @@ public abstract class Player
 
     public void wakeUpPlayer(boolean flag, boolean flag1)
     {
-        setSize(0.6F, 1.8F);
-        resetHeight();
+        setupScale();
         ChunkCoordinates chunkcoordinates = bedChunkCoordinates;
         Block<?> b;
         if(chunkcoordinates != null && (b = world.getBlock(chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z)) != null && b.getLogic() instanceof BlockLogicBed)
diff --git a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileFireball.java b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileFireball.java
index 22d7136bf..2dcb5d22a 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileFireball.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileFireball.java
@@ -113,7 +113,7 @@ public class ProjectileFireball extends Projectile
         markHurt();
         if(entity != null)
         {
-            Vec3 lookAngle = entity.getLookAngle();
+            Vec3 lookAngle = entity.getViewVector(1);
             if (entity instanceof Mob){
                 this.owner = (Mob) entity;
             }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemBucket.java b/game/core/src/main/java/net/minecraft/core/item/ItemBucket.java
index 2b6e2d6ed..0214ee54f 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemBucket.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemBucket.java
@@ -10,7 +10,6 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.Side;
-import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.Nullable;
 
@@ -34,7 +33,7 @@ public class ItemBucket extends Item
 		}
 
 		double reachDistance = player.getGamemode().getBlockReachDistance();
-		HitResult rayTraceResult = player.rayTrace(reachDistance, 1f, false, false);
+		HitResult rayTraceResult = player.rayTrace(reachDistance, 1f, false, false, false);
 		
 		if(rayTraceResult == null || rayTraceResult.hitType != HitResult.HitType.TILE) {
 			return stack;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemBucketEmpty.java b/game/core/src/main/java/net/minecraft/core/item/ItemBucketEmpty.java
index 14ed270b6..45971bf95 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemBucketEmpty.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemBucketEmpty.java
@@ -25,7 +25,7 @@ public class ItemBucketEmpty extends Item
     public ItemStack onUseItem(ItemStack itemstack, World world, Player entityplayer)
     {
         double reachDistance = entityplayer.getGamemode().getBlockReachDistance();
-        HitResult hitResult = entityplayer.rayTrace(reachDistance, 1f, true, false);
+        HitResult hitResult = entityplayer.rayTrace(reachDistance, 1f, true, false, false);
 
         if(hitResult == null)
         {
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemWandSpawner.java b/game/core/src/main/java/net/minecraft/core/item/ItemWandSpawner.java
index cc1f8ef29..0468892fe 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemWandSpawner.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemWandSpawner.java
@@ -27,7 +27,7 @@ public class ItemWandSpawner extends Item implements IDispensable
 
         if (!player.isSneaking()){
             double reachDistance = player.getGamemode().getBlockReachDistance();
-            HitResult rayTraceResult = player.rayTrace(reachDistance, 1f, false, false);
+            HitResult rayTraceResult = player.rayTrace(reachDistance, 1f, false, false, false);
 
             if (rayTraceResult != null){
                 if (!world.isClientSide){
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockAlgae.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockAlgae.java
index 7dd11f4ab..29b1454ae 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockAlgae.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockAlgae.java
@@ -37,7 +37,7 @@ public class ItemBlockAlgae<T extends BlockLogic> extends ItemBlock<T>
     public ItemStack onUseItem(ItemStack itemstack, World world, Player player)
     {
         double reachDistance = player.getGamemode().getBlockReachDistance();
-        HitResult rayTraceResult = player.rayTrace(reachDistance, 1f, true, false);
+        HitResult rayTraceResult = player.rayTrace(reachDistance, 1f, true, false, false);
         if(rayTraceResult == null)
         {
             return itemstack;
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 964b4fe7b..6b10221f7 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
@@ -1460,7 +1460,7 @@ public class World implements WorldSource {
     {
         listeners.remove(iworldaccess);
     }
-    public List<AABB> getCubes(Entity entity, AABB aabb)
+    public @NotNull List<AABB> getCubes(Entity entity, AABB aabb)
     {
         collidingBoundingBoxes.clear();
 
@@ -2183,6 +2183,7 @@ public class World implements WorldSource {
     @Override
     public boolean isBlockNormalCube(int x, int y, int z)
     {
+        // Determines if you suffocate in a block, among other things
         Block<?> block = Blocks.blocksList[getBlockId(x, y, z)];
         if(block == null)
         {
@@ -2384,18 +2385,19 @@ public class World implements WorldSource {
                 int weatherBlockZ = (randVal / (Chunk.CHUNK_SIZE_Z * Chunk.CHUNK_SIZE_X)) & (Chunk.CHUNK_SIZE_Z - 1);
                 getCurrentWeather().doEnvironmentUpdate(this, rand, chunkBlockX + weatherBlockX, chunkBlockZ + weatherBlockZ);
             }
-
-            for (int i = 0; i < 80; i++) {
-                updateLCG = updateLCG * 3 + 0x3c6ef35f;
-                int iRandVal = updateLCG >> 2;
-                int iBlockX = iRandVal & (Chunk.CHUNK_SIZE_X - 1);
-                int iBlockZ = (iRandVal / (Chunk.CHUNK_SIZE_Z * Chunk.CHUNK_SIZE_X)) & (Chunk.CHUNK_SIZE_Z - 1);
-                int iBlockY = (iRandVal / (HEIGHT_BLOCKS * Chunk.CHUNK_SIZE_Z * Chunk.CHUNK_SIZE_X)) & (HEIGHT_BLOCKS - 1);
-                int id = chunk.getBlockID(iBlockX, iBlockY, iBlockZ);
-                if (Blocks.shouldTick[id]) {
-                    Blocks.blocksList[id].updateTick(this, iBlockX + chunkBlockX, iBlockY, iBlockZ + chunkBlockZ, rand);
+            
+            for (int s = 0; s < Chunk.CHUNK_SECTIONS; s++) {
+                for (int i = 0; i < 10; i++) {
+                    updateLCG = updateLCG * 3 + 0x3c6ef35f;
+                    int iRandVal = updateLCG >> 2;
+                    int iBlockX = iRandVal & (Chunk.CHUNK_SIZE_X - 1);
+                    int iBlockZ = (iRandVal / (Chunk.CHUNK_SIZE_Z * Chunk.CHUNK_SIZE_X)) & (Chunk.CHUNK_SIZE_Z - 1);
+                    int iBlockY = (iRandVal / (ChunkSection.SECTION_SIZE_Y * Chunk.CHUNK_SIZE_Z * Chunk.CHUNK_SIZE_X)) & (ChunkSection.SECTION_SIZE_Y - 1) + s * ChunkSection.SECTION_SIZE_Y;
+                    int id = chunk.getBlockID(iBlockX, iBlockY, iBlockZ);
+                    if (Blocks.shouldTick[id]) {
+                        Blocks.blocksList[id].updateTick(this, iBlockX + chunkBlockX, iBlockY, iBlockZ + chunkBlockZ, this.rand);
+                    }
                 }
-                i++;
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/data/BiomeRangeLookup.java b/game/core/src/main/java/net/minecraft/core/world/biome/data/BiomeRangeLookup.java
index fcf09c3c7..0b5f4875d 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/data/BiomeRangeLookup.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/data/BiomeRangeLookup.java
@@ -1,65 +1,92 @@
 package net.minecraft.core.world.biome.data;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.world.biome.Biome;
+import org.slf4j.Logger;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 public class BiomeRangeLookup
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private final byte[] lookup;
     private final int span;
 
-    public BiomeRangeLookup(BiomeRangeMap map, int span)
+    public BiomeRangeLookup(final BiomeRangeMap map, final int span)
     {
         this.lookup = new byte[span * span * span * span];
         this.span = span;
 
+        // Since sampling span^4 times is a bit slow the task is split among multiple threads in order to speed of the process
+
+        final ExecutorService service = Executors.newFixedThreadPool(10);
+        final Future<?>[] tasks = new Future[span * span];
+
         for (int iTemperature = 0; iTemperature < span; iTemperature++)
         {
             for (int iHumidity = 0; iHumidity < span; iHumidity++)
             {
-                for (int iAltitude = 0; iAltitude < span; iAltitude++)
-                {
-                    for (int iVariety = 0; iVariety < span; iVariety++)
-                    {
-                        Biome biome = map.findBiome(
-                                iTemperature / (double)span,
-                                iHumidity / (double)span,
-                                iAltitude / (double)span,
-                                iVariety / (double)span
-                        );
-                        if (biome == null) throw new RuntimeException("Biome at T: " + iTemperature / 50f + " H: " + iHumidity / 50f + " A: " + iAltitude / 50f + " V: " + iVariety / 50f + " is null!");
-                        setBiome(iTemperature, iHumidity, iAltitude, iVariety, biome);
-                    }
-                }
+                final int finalITemperature = iTemperature;
+                final int finalIHumidity = iHumidity;
+                tasks[iTemperature * span + iHumidity] = service.submit(() -> setupSubTask(map, finalITemperature, finalIHumidity));
+            }
+        }
+        for (int i = 0; i < tasks.length; i++) {
+            try {
+                tasks[i].get();
+            } catch (final InterruptedException | ExecutionException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        service.shutdown();
+    }
+
+    private void setupSubTask(final BiomeRangeMap map, final int iTemperature, final int iHumidity) {
+        for (int iAltitude = 0; iAltitude < this.span; iAltitude++)
+        {
+            for (int iVariety = 0; iVariety < this.span; iVariety++)
+            {
+                final Biome biome = map.findBiome(
+                    iTemperature / (double) this.span,
+                    iHumidity / (double) this.span,
+                    iAltitude / (double) this.span,
+                    iVariety / (double) this.span
+                );
+                if (biome == null) throw new RuntimeException("Biome at T: " + iTemperature / ((float) this.span) + " H: " + iHumidity / ((float) this.span) + " A: " + iAltitude / ((float) this.span) + " V: " + iVariety / ((float) this.span) + " is null!");
+                setBiome(iTemperature, iHumidity, iAltitude, iVariety, biome);
             }
         }
     }
 
-    private void setBiome(int temperature, int humidity, int altitude, int variety, Biome biome)
+    private void setBiome(final int temperature, final int humidity, final int altitude, final int variety, final Biome biome)
     {
-        this.lookup[(variety * span * span * span) + (altitude * span * span) + (humidity * span) + (temperature)] = (byte) Registries.BIOMES.getNumericIdOfItem(biome);
+        this.lookup[(variety * this.span * this.span * this.span) + (altitude * this.span * this.span) + (humidity * this.span) + (temperature)] = (byte) Registries.BIOMES.getNumericIdOfItem(biome);
     }
 
-    public Biome getBiome(double temperature, double humidity, double altitude, double variety)
+    public Biome getBiome(final double temperature, final double humidity, final double altitude, final double variety)
     {
-        int iTemperature = integerize(temperature);
-        int iHumidity = integerize(humidity);
-        int iAltitude = integerize(altitude);
-        int iVariety = integerize(variety);
+        final int iTemperature = integerize(temperature);
+        final int iHumidity = integerize(humidity);
+        final int iAltitude = integerize(altitude);
+        final int iVariety = integerize(variety);
 
         return Registries.BIOMES.getItemByNumericId(this.lookup[
-                (iVariety * span * span * span) +
-                (iAltitude * span * span) +
-                (iHumidity * span) +
+                (iVariety * this.span * this.span * this.span) +
+                (iAltitude * this.span * this.span) +
+                (iHumidity * this.span) +
                 (iTemperature)
         ]);
     }
 
-    private int integerize(double d)
+    private int integerize(final double d)
     {
-        int i = (int)(d * span);
+        int i = (int)(d * this.span);
         if (i < 0) i = 0;
-        if (i >= span) i = span - 1;
+        if (i >= this.span) i = this.span - 1;
         return i;
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/season/Season.java b/game/core/src/main/java/net/minecraft/core/world/season/Season.java
index e05d357b8..c6401a185 100644
--- a/game/core/src/main/java/net/minecraft/core/world/season/Season.java
+++ b/game/core/src/main/java/net/minecraft/core/world/season/Season.java
@@ -71,6 +71,7 @@ public abstract class Season
 		return this;
 	}
 
+	// todo: Unused as we are removing the seasonal sapling drop factor
 	public Season setSaplingDropFactor(float saplingDropFactor)
 	{
 		this.saplingDropFactor = saplingDropFactor;
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 54aa221c8..20759bd6f 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
@@ -73,7 +73,6 @@ public class PlayerServer extends Player implements ContainerListener {
         footSize = 0.0F;
         this.username = username;
         this.uuid = uuid;
-        heightOffset = 0.0F;
         gamemode = minecraftserver.defaultGamemode;
     }
 
@@ -177,18 +176,6 @@ public class PlayerServer extends Player implements ContainerListener {
         return playerInventory;
     }
 
-    @Override
-	protected void resetHeight()
-    {
-        heightOffset = 0.0F;
-    }
-
-    @Override
-	public float getHeadHeight()
-    {
-        return getHeightOffset(); // since server player heights and y values aren't synced, this is correct for server but not the client
-    }
-
     @Override
 	public void tick()
     {
