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 967c41a63..d219fe60f 100644
--- a/game/client/src/main/java/net/minecraft/client/Minecraft.java
+++ b/game/client/src/main/java/net/minecraft/client/Minecraft.java
@@ -24,7 +24,6 @@ import net.minecraft.client.gui.*;
 import net.minecraft.client.gui.achievements.ScreenAchievements;
 import net.minecraft.client.gui.chat.ScreenChat;
 import net.minecraft.client.gui.chat.ScreenSleepMP;
-import net.minecraft.client.gui.options.data.OptionsPage;
 import net.minecraft.client.gui.options.data.OptionsPages;
 import net.minecraft.client.gui.toasts.GuiElementToastsHud;
 import net.minecraft.client.holiday.Holidays;
@@ -59,7 +58,7 @@ import net.minecraft.core.net.command.commands.CommandSeed;
 import net.minecraft.core.net.command.commands.CommandSetBlock;
 import net.minecraft.core.net.command.commands.CommandSetSpawn;
 import net.minecraft.core.net.command.commands.CommandSpawn;
-import net.minecraft.core.net.command.commands.CommandSpawnParticle;
+import net.minecraft.core.net.command.commands.CommandParticle;
 import net.minecraft.core.net.command.commands.CommandSummon;
 import net.minecraft.core.net.command.commands.CommandTeleport;
 import net.minecraft.core.net.command.commands.CommandTellRaw;
@@ -128,7 +127,6 @@ import net.minecraft.client.render.shader.ShadersRenderer;
 import net.minecraft.client.render.terrain.ChunkRenderer;
 import net.minecraft.client.render.terrain.TerrainRenderer;
 import net.minecraft.client.render.terrain.TerrainRendererLegacy;
-import net.minecraft.client.render.terrain.TerrainRendererMultiDraw;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.texturepack.TexturePackList;
@@ -714,7 +712,7 @@ public class Minecraft
         CommandManager.registerCommand(new CommandHeal());
         CommandManager.registerCommand(new CommandMobSpawning());
         CommandManager.registerCommand(new CommandPlaySound());
-        CommandManager.registerCommand(new CommandSpawnParticle());
+        CommandManager.registerCommand(new CommandParticle());
     }
     
     private void printWrongJavaVersionInfo() {
@@ -1421,7 +1419,7 @@ public class Minecraft
         }
     }
 
-    private void clickMiddleMouseButton()
+    private void clickMiddleMouseButton(boolean shift, boolean control)
     {
         HitResult mouseOver = thePlayer.rayTrace(256, timer.partialTicks, false, false);
         if(mouseOver != null && mouseOver.hitType == HitResult.HitType.TILE)
@@ -1429,7 +1427,7 @@ public class Minecraft
             int x = mouseOver.x;
             int y = mouseOver.y;
             int z = mouseOver.z;
-            thePlayer.pickBlock(x, y, z);
+            thePlayer.pickBlock(x, y, z, control);
         }
     }
 
@@ -1865,7 +1863,7 @@ public class Minecraft
 
         // Pick block
         if (gameSettings.keyPickBlock.isPressEvent(currentInputDevice)) {
-            clickMiddleMouseButton();
+            clickMiddleMouseButton(shift, control);
             return true;
         }
 
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 a1d134c22..9421d05ab 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
@@ -71,6 +71,13 @@ public class PlayerLocal extends Player
         uuid = session.uuid;
 
         playerConfig.setLeftHand(minecraft.gameSettings.playerLeftHanded.value);
+        playerConfig.setCape(minecraft.gameSettings.playerCape.value);
+        playerConfig.setHat(minecraft.gameSettings.playerHat.value);
+        playerConfig.setJacket(minecraft.gameSettings.playerJacket.value);
+        playerConfig.setSleeveLeft(minecraft.gameSettings.playerSleeveLeft.value);
+        playerConfig.setSleeveRight(minecraft.gameSettings.playerSleeveRight.value);
+        playerConfig.setPantLeft(minecraft.gameSettings.playerPantLeft.value);
+        playerConfig.setPantRight(minecraft.gameSettings.playerPantRight.value);
 
         new GetSkinUrlThread(this);
         LOGGER.info("logged in with session name: {}", username);
diff --git a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocalMultiplayer.java b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocalMultiplayer.java
index 1f68a30b4..d96ea6cb2 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocalMultiplayer.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocalMultiplayer.java
@@ -11,7 +11,6 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.entity.vehicle.EntityBoat;
 import net.minecraft.core.net.packet.PacketBoatControl;
 import net.minecraft.core.net.packet.PacketChat;
-import net.minecraft.core.net.packet.PacketContainerSetSlot;
 import net.minecraft.core.net.packet.PacketPlayerConfig;
 import net.minecraft.core.net.packet.PacketUpdatePlayerState;
 import net.minecraft.core.net.packet.PacketMovePlayer;
@@ -277,8 +276,8 @@ public class PlayerLocalMultiplayer extends PlayerLocal implements Player.Player
     }
     
     @Override
-    public void pickBlock(int x, int y, int z) {
-    	sendQueue.addToSendQueue(new PacketPlayerAction(PacketPlayerAction.ACTION_PICK_BLOCK, x, y, z, Side.NONE, 0.0, 0.0));
+    public void pickBlock(int x, int y, int z, boolean pickFully) {
+    	sendQueue.addToSendQueue(new PacketPlayerAction(pickFully ? PacketPlayerAction.ACTION_PICK_BLOCK_FULLY : PacketPlayerAction.ACTION_PICK_BLOCK, x, y, z, Side.NONE, 0.0, 0.0));
     }
 
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java
index 46ca59dcc..1c250c023 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java
@@ -118,7 +118,7 @@ public class ScreenMainMenu extends Screen
                 codeProgress = 0;
             }
         }
-        else
+        else if (eventKey != -1)
         {
             codeProgress = 0;
         }
@@ -384,7 +384,7 @@ public class ScreenMainMenu extends Screen
     	}
     }
 
-    private void drawLogo(float var1) {
+    private void drawLogo(final float partialTick) {
         int var3;
         if(this.logoBlocks == null) {
             this.logoBlocks = new LogoBlock[logoBlockLayers[0].length()][logoBlockLayers.length];
@@ -399,7 +399,7 @@ public class ScreenMainMenu extends Screen
         GL11.glMatrixMode(GL11.GL_PROJECTION);
         GL11.glPushMatrix();
         GL11.glLoadIdentity();
-        int delta = mc.gameWindow.getWidthPixels() / mc.resolution.getScaledWidthScreenCoords();
+        final int delta = this.mc.gameWindow.getWidthPixels() / this.mc.resolution.getScaledWidthScreenCoords();
         var3 = 120 * delta;
         GLU.gluPerspective(70.0F, (float)this.mc.gameWindow.getWidthPixels() / (float)var3, 0.05F, 100.0F);
         GL11.glViewport(0, this.mc.gameWindow.getHeightPixels() - var3, this.mc.gameWindow.getWidthPixels(), var3);
@@ -410,27 +410,27 @@ public class ScreenMainMenu extends Screen
         GL11.glCullFace(GL11.GL_BACK);
         GL11.glDepthMask(true);
         GL11.glEnable(GL11.GL_DEPTH_TEST);
-        Lighting.enableLight();
+        Lighting.enableLight(0.5f, 0.16f);
         
-        for(int var4 = 0; var4 < 3; ++var4) {
+        for(int renderPass = 0; renderPass < 3; ++renderPass) {
             GL11.glPushMatrix();
             GL11.glTranslatef(0.4F, 0.6F, -12.0F);
-            if(var4 == 0) {
-                GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
-                GL11.glTranslatef(0.0F, -0.4F, 0.0F);
-                GL11.glScalef(0.98F, 1.0F, 1.0F);
-                GL11.glEnable(GL11.GL_BLEND);
-                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-            }
-
-            if(var4 == 1) {
-                GL11.glDisable(GL11.GL_BLEND);
-                GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
-            }
-
-            if(var4 == 2) {
-                GL11.glEnable(GL11.GL_BLEND);
-                GL11.glBlendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE);
+            switch (renderPass) {
+                case 0:
+                    GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
+                    GL11.glTranslatef(0.0F, -0.4F, 0.0F);
+                    GL11.glScalef(0.98F, 1.0F, 1.0F);
+                    GL11.glEnable(GL11.GL_BLEND);
+                    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+                    break;
+                case 1:
+                    GL11.glDisable(GL11.GL_BLEND);
+                    GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
+                    break;
+                case 2:
+                    GL11.glEnable(GL11.GL_BLEND);
+                    GL11.glBlendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE);
+                    break;
             }
 
             GL11.glScalef(1.0F, -1.0F, 1.0F);
@@ -438,20 +438,20 @@ public class ScreenMainMenu extends Screen
             GL11.glScalef(0.89F, 1.0F, 0.4F);
             GL11.glTranslatef((float)(-logoBlockLayers[0].length()) * 0.5F, (float)(-logoBlockLayers.length) * 0.5F, 0.0F);
             TextureRegistry.blockAtlas.bind();
-            if(var4 == 0) {
+            if(renderPass == 0) {
                 this.mc.textureManager.loadTexture("/title/black.png").bind();
             }
 
             for(int y = 0; y < logoBlockLayers.length; ++y) {
                 for(int x = 0; x < logoBlockLayers[y].length(); ++x) {
-                    char var8 = logoBlockLayers[y].charAt(x);
-                    if(var8 != ' ') {
+                    char c = logoBlockLayers[y].charAt(x);
+                    if(c != ' ') {
                         GL11.glPushMatrix();
-                        LogoBlock var9 = this.logoBlocks[x][y];
-                        float z = (float)(var9.prevHeight + (var9.height - var9.prevHeight) * (double)var1);
+                        final LogoBlock logoBlock = this.logoBlocks[x][y];
+                        float z = (float)(logoBlock.prevHeight + (logoBlock.height - logoBlock.prevHeight) * (double)partialTick);
                         float scale = 1.0F;
                         float alpha = 1.0F;
-                        if(var4 == 0) {
+                        if(renderPass == 0) {
                             scale = z * 0.04F + 1.0F;
                             alpha = 1.0F / scale;
                             z = 0.0F;
@@ -459,7 +459,7 @@ public class ScreenMainMenu extends Screen
 
                         GL11.glTranslatef(x, y, z);
                         GL11.glScalef(scale, scale, scale);
-                        BlockModelDispatcher.getInstance().getDispatch(BLOCKS_TO_DRAW[indexToDraw]).renderStandalone(Tessellator.instance, 0, 1f, alpha, null);
+                        BlockModelDispatcher.getInstance().getDispatch(BLOCKS_TO_DRAW[this.indexToDraw]).renderStandalone(Tessellator.instance, 0, 1f, alpha, null);
                         GL11.glPopMatrix();
                     }
                 }
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 ff44062bb..f768851c5 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
@@ -240,6 +240,7 @@ public class TooltipElement extends Gui
 		if(discovered) {
 			text.append(TextFormatting.get(itemStack.getDisplayColor()));
 			text.append(itemStack.getDisplayName());
+            if (itemStack.getData().containsKey("tileEntityData")) text.append(" ").append(TextFormatting.MAGENTA).append(TextFormatting.ITALIC).append("+NBT").append(TextFormatting.RESET).append(TextFormatting.get(itemStack.getDisplayColor()));
 
 
             if(debug) {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/chat/GuiElementChatSuggestions.java b/game/client/src/main/java/net/minecraft/client/gui/chat/GuiElementChatSuggestions.java
index f6082c1c2..53731bc4c 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/chat/GuiElementChatSuggestions.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/chat/GuiElementChatSuggestions.java
@@ -340,7 +340,7 @@ public class GuiElementChatSuggestions extends Gui {
     }
 
     public void scroll(int amount) {
-        this.scroll = MathHelper.clamp(scroll + amount, 0, this.suggestions.size() - MAX_SUGGESTIONS);
+        this.scroll = MathHelper.clamp(scroll + amount, 0, Math.max(this.suggestions.size() - MAX_SUGGESTIONS, 0));
     }
 
     public void cycleThroughSuggestions() {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/chat/ScreenChat.java b/game/client/src/main/java/net/minecraft/client/gui/chat/ScreenChat.java
index 044ca43de..26d4e249a 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/chat/ScreenChat.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/chat/ScreenChat.java
@@ -1,5 +1,6 @@
 package net.minecraft.client.gui.chat;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.hud.component.ComponentAnchor;
 import net.minecraft.client.gui.keyboard.ScreenKeyboard;
@@ -11,9 +12,10 @@ import org.lwjgl.input.Keyboard;
 
 import net.minecraft.client.gui.text.ITextField;
 import org.lwjgl.input.Mouse;
+import org.slf4j.Logger;
 
 public class ScreenChat extends Screen implements ITextField {
-
+	protected static final Logger LOGGER = LogUtils.getLogger();
 	protected String message;
 	private int currentIndex = 0;
 	private String originalMessage;
@@ -183,40 +185,44 @@ public class ScreenChat extends Screen implements ITextField {
 
 	@Override
 	public void render(int mx, int my, float partialTick) {
-		// Draw emote picker button
-		int emotePickerButtonColor = 0x80000000;
-		int emotePickerTextColor = 0xE0E0E0;
-		if (mx >= 2 && mx < 14 && my >= height - 14 && my < height - 2)
-		{
-			emotePickerButtonColor = 0x80ffffff;
-			emotePickerTextColor = 0xffffffa0;
-		}
-		drawRect(2, height - 14, 14, height - 2, emotePickerButtonColor);
-		drawStringCentered(font, Character.toString('\u263a'), 2 + 6, height - 12, emotePickerTextColor);
+		try {
+			// Draw emote picker button
+			int emotePickerButtonColor = 0x80000000;
+			int emotePickerTextColor = 0xE0E0E0;
+			if (mx >= 2 && mx < 14 && my >= height - 14 && my < height - 2)
+			{
+				emotePickerButtonColor = 0x80ffffff;
+				emotePickerTextColor = 0xffffffa0;
+			}
+			drawRect(2, height - 14, 14, height - 2, emotePickerButtonColor);
+			drawStringCentered(font, Character.toString('\u263a'), 2 + 6, height - 12, emotePickerTextColor);
 
-		drawRect(16, height - 14, width - 2, height - 2, 0x80000000);
+			drawRect(16, height - 14, width - 2, height - 2, 0x80000000);
 
-		font.drawStringWithShadow(this.suggestionsElement.getSuggestionPreview(), 16 + suggestionsElement.getDefaultParameterPosition(), mc.resolution.getScaledHeightScreenCoords() - 12, 0xFFFFFF);
-		drawString(font, this.suggestionsElement.colorCodeText(message, true), 18, height - 12, 0xE0E0E0);
-		boolean drawCursor = (updateCounter / 6) % 2 == 0;
-		int cursor = editor.getCursor();
-		if (drawCursor)
-		{
-			int width = font.getStringWidth(message);
-			if (cursor < message.length())
+			font.drawStringWithShadow(this.suggestionsElement.getSuggestionPreview(), 16 + suggestionsElement.getDefaultParameterPosition(), mc.resolution.getScaledHeightScreenCoords() - 12, 0xFFFFFF);
+			boolean drawCursor = (updateCounter / 6) % 2 == 0;
+			int cursor = editor.getCursor();
+			drawString(font, this.suggestionsElement.colorCodeText(message, true), 18, height - 12, 0xE0E0E0);
+			if (drawCursor)
 			{
-				width = font.getStringWidth(message.substring(0, cursor));
+				int width = font.getStringWidth(message);
+				if (cursor < message.length())
+				{
+					width = font.getStringWidth(message.substring(0, cursor));
+				}
+				drawString(font, "_", 18 + width, height - 12, 0xE0E0E0);
 			}
-			drawString(font, "_", 18 + width, height - 12, 0xE0E0E0);
-		}
 
-		if (showEmotePicker) {
-			emotePicker.draw(2, height - 16 - emotePicker.getHeight(), mx, my);
-		}
+			if (showEmotePicker) {
+				emotePicker.draw(2, height - 16 - emotePicker.getHeight(), mx, my);
+			}
 
-		super.render(mx, my, partialTick);
-		if (this.suggestionsElement != null) {
-			this.suggestionsElement.drawScreen();
+			super.render(mx, my, partialTick);
+			if (this.suggestionsElement != null) {
+				this.suggestionsElement.drawScreen();
+			}
+		} catch (Exception e) {
+			LOGGER.error("Exception while attempting to render chat gui!", e);
 		}
 	}
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
index b8b4df54c..4a308f6da 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
@@ -106,22 +106,22 @@ public class HudIngame extends Gui
         }
 
         // Render pumpkin overlay
-        ItemStack headSlotItem = mc.thePlayer.getItemInArmorSlot(HumanArmorShape.HEAD);
-        if (mc.gameSettings.thirdPersonView.value == 0 && headSlotItem != null && (headSlotItem.itemID == Blocks.PUMPKIN_CARVED_IDLE.id() || headSlotItem.itemID == Blocks.PUMPKIN_REDSTONE.id()))
+        final ItemStack headSlotItem = this.mc.thePlayer.inventory.armorItemInSlot(HumanArmorShape.HEAD);
+        if (this.mc.gameSettings.thirdPersonView.value == 0 && headSlotItem != null && (headSlotItem.itemID == Blocks.PUMPKIN_CARVED_IDLE.id() || headSlotItem.itemID == Blocks.PUMPKIN_REDSTONE.id()))
         {
             renderPumpkinBlur(width, height);
         }
 
         // Render portal overlay
-        float portalIntensity = mc.thePlayer.prevTimeInPortal + (mc.thePlayer.timeInPortal - mc.thePlayer.prevTimeInPortal) * partialTicks;
+        final float portalIntensity = MathHelper.lerp(this.mc.thePlayer.prevTimeInPortal, this.mc.thePlayer.timeInPortal, partialTicks);
         if (portalIntensity > 0.0F)
         {
             renderPortalOverlay(portalIntensity, width, height);
         }
 
-        for (HudComponent component : HudComponents.INSTANCE.getComponents()) {
-            if (component.isVisible(mc) && component.isEnabled(mc)) {
-                component.render(mc, this, width - sp * 2, height - sp * 2, partialTicks);
+        for (final HudComponent component : HudComponents.INSTANCE.getComponents()) {
+            if (component.isVisible(this.mc)) {
+                component.render(this.mc, this, width - sp * 2, height - sp * 2, partialTicks);
             }
         }
 
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 2627145ab..855f530a5 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
@@ -381,7 +381,7 @@ public class ScreenModelViewer extends ScreenPhotoMode implements ListenerTextFi
 
         scroll(Mouse.getDWheel());
 
-        TileEntityRenderDispatcher.instance.renderTileEntity(Tessellator.instance, new TileEntity(), -0.5D, -0.75D, -0.5D, partialTick);
+//        TileEntityRenderDispatcher.instance.renderTileEntity(Tessellator.instance, new TileEntity(), -0.5D, -0.75D, -0.5D, partialTick);
 
         drawStringCentered(font, currentCategory.getCurrentDisplayInfo(I18n.getInstance()), width/2, 1, 0xffffff);
     }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java b/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
index 4472d7644..0a474d34d 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
@@ -32,10 +32,11 @@ public abstract class OptionsPages
     private static final Minecraft mc = Minecraft.getMinecraft();
     private static boolean hasInit = false;
     public static OptionsPage GENERAL;
-
+    public static OptionsPage PLAYER;
     public static OptionsPage AUDIO;
     public static OptionsPage VIDEO;
     public static OptionsPage CONTROLS;
+    public static OptionsPage ACCESSIBILITY;
     public static OptionsPage TEXTURE_PACKS;
     public static OptionsPage LANGUAGE;
     public static OptionsPage SEARCH;
@@ -60,7 +61,6 @@ public abstract class OptionsPages
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.autoHit))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.easyBridge))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.viewBobbing))
-                .withComponent(new BooleanOptionComponent(mc.gameSettings.playerLeftHanded))
             )
             .withComponent(new OptionsCategory("gui.options.page.general.category.user_interface")
                 .withComponent(new ShortcutComponent("gui.options.page.general.button.edit_hud", () -> mc.displayScreen(new ScreenHudDesigner(mc.currentScreen))))
@@ -86,12 +86,26 @@ public abstract class OptionsPages
             )
             .withComponent(new ShortcutComponent("gui.options.page.general.button.open_worlds_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "saves"))))
             .withComponent(new ShortcutComponent("gui.options.page.general.button.open_screenshots_folder", () -> {
-                File f = new File(mc.getMinecraftDir(), "screenshots");
+                final File f = new File(mc.getMinecraftDir(), "screenshots");
+                //noinspection ResultOfMethodCallIgnored
                 f.mkdirs();
                 Utils.openDirectory(f);
             }))
         );
 
+        PLAYER = register(new OptionsPage("gui.options.page.player.title", new ItemStack(Items.STATUE_STONE))
+            .withComponent(new OptionsCategory("gui.options.page.player.category.player")
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.playerLeftHanded))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.playerCape))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.playerHat))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.playerJacket))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.playerSleeveLeft))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.playerSleeveRight))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.playerPantLeft))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.playerPantRight))
+            )
+        );
+
         AUDIO = register(new OptionsPage("gui.options.page.audio.title", new ItemStack(Items.RECORD_CAT))
             .withComponent(new OptionsCategory("gui.options.page.audio.category.audio")
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.subtitles))
@@ -106,7 +120,7 @@ public abstract class OptionsPages
             )
         );
 
-        ToggleableOptionComponent<?> lightmapComponent = new ToggleableOptionComponent<>(mc.gameSettings.lightmapStyle);
+        final OptionsComponent lightmapComponent = new ToggleableOptionComponent<>(mc.gameSettings.lightmapStyle);
 
         VIDEO = register(new OptionsPage("gui.options.page.video.title", new ItemStack(Items.FLAG))
             .withComponent(new OptionsCategory("gui.options.page.video.category.graphics")
@@ -135,6 +149,8 @@ public abstract class OptionsPages
             .withComponent(new OptionsCategory("gui.options.page.video.category.visuals")
                 .withComponent(Minecraft.GPU_VENDOR == EnumGPUVendor.INTEL ? null : lightmapComponent)
                 .withComponent(new FloatOptionComponent(mc.gameSettings.brightness))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.fovModification))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.screenMotionEffects))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.fog))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.biomeWater))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.treeShadows))
@@ -238,6 +254,20 @@ public abstract class OptionsPages
                 .withComponent(new KeyBindingComponent(mc.gameSettings.keyShowConsole))
             )
         );
+
+        ACCESSIBILITY = register(new OptionsPage("gui.options.page.accessibility.title", new ItemStack(Items.WAND_MONSTER_SPAWNER))
+            .withComponent(new OptionsCategory("gui.options.page.accessibility.category.accessibility")
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.subtitles))
+                .withComponent(new IntegerOptionComponent(mc.gameSettings.guiScale))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.screenPadding))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.viewBobbing))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.fovModification))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.screenMotionEffects))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.colorblindnessFix))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.turnWithVehicle))
+            )
+        );
+
         TEXTURE_PACKS = register(new OptionsPage("gui.options.page.texture_packs.title", new ItemStack(Items.PAINTING))
             .withComponent(new ShortcutComponent("gui.options.page.texture_packs.button.open_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "texturepacks"))))
             .withComponent(new OptionsCategory("gui.options.page.texture_packs.category.textures")
@@ -309,8 +339,8 @@ public abstract class OptionsPages
                                    mc.changeWorld(new WorldClient(), "Loading Model Viewer");
                                    mc.displayScreen(new ScreenModelViewer());}) {
                                    @Override
-                                   public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) {
-                                       button.enabled = mc.currentWorld == null;
+                                   public void render(final int x, final int y, final int width, final int relativeMouseX, final int relativeMouseY) {
+                                       this.button.enabled = mc.currentWorld == null;
                                        super.render(x, y, width, relativeMouseX, relativeMouseY);
                                    }
                                }
@@ -330,7 +360,7 @@ public abstract class OptionsPages
             )
             .withComponent(new OptionsCategory("gui.options.page.debug.category.test")
                 .withComponent(new ShortcutComponent("gui.options.page.debug.button.music.skip", () -> {
-                    SoundSystem soundSystem = SoundEngine.getSoundSystem();
+                    final SoundSystem soundSystem = SoundEngine.getSoundSystem();
                     if (soundSystem != null) {
                         soundSystem.stop(SoundEngine.BG_MUSIC);
                     }
@@ -341,8 +371,8 @@ public abstract class OptionsPages
                     mc.currentWorld.getLevelData().setCheatsEnabled(true);
                 }) {
                     @Override
-                    public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) {
-                        button.enabled = (mc.currentWorld != null && !mc.currentWorld.isClientSide);
+                    public void render(final int x, final int y, final int width, final int relativeMouseX, final int relativeMouseY) {
+                        this.button.enabled = (mc.currentWorld != null && !mc.currentWorld.isClientSide);
                         super.render(x, y, width, relativeMouseX, relativeMouseY);
                     }
                 })
@@ -350,7 +380,7 @@ public abstract class OptionsPages
                     mc.statsCounter.wipe("I want to delete all the saved stats");
                 }))
                 .withComponent(new ShortcutComponent("gui.options.page.debug.button.unlockedall", () -> {
-                    for (Stat stat : StatList.getAllStats()){
+                    for (final Stat stat : StatList.getAllStats()){
                         mc.thePlayer.addStat(stat, mc.thePlayer.getStat(stat) == 0 ? 1 : 0);
                     }
                 }))
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 bf45585fa..03df1d9c5 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
@@ -128,7 +128,7 @@ public class GameSettings {
 	public OptionEnum<RenderScale> renderScale = new OptionEnum<>(this, "renderScale", RenderScale.class, RenderScale.SCALE_100);
 	public OptionBoolean heatHaze = new OptionBoolean(this, "heatHaze", false);
 	public OptionBoolean alphaMenu = new OptionBoolean(this, "old", false);
-	public OptionBoolean enableItemClumping = new OptionBoolean(this, "enableItemClumping", false);
+	public OptionBoolean enableItemClumping = new OptionBoolean(this, "enableItemClumping", true);
 	public OptionBoolean alwaysShowDescriptions = new OptionBoolean(this, "alwaysShowDescriptions", false);
 	public OptionBoolean turnWithVehicle = new OptionBoolean(this, "turnWithVehicle", true);
 	public OptionBoolean disableCrashHandler = new OptionBoolean(this, "disableCrashHandler", false);
@@ -157,6 +157,9 @@ public class GameSettings {
 	public OptionRange mipmapLevels = new OptionRange(this, "mipmapLevels", 0, 5);
 	public OptionEnum<MipmapType> mipmapType = new OptionEnum<>(this, "mipmapType", MipmapType.class, MipmapType.SMOOTH);
 
+	public OptionBoolean fovModification = new OptionBoolean(this, "fov.modification", true);
+	public OptionBoolean screenMotionEffects = new OptionBoolean(this, "screen.motion.effects", true);
+
 	public OptionBoolean fullscreen = new OptionBoolean(this, "fullscreen", Minecraft.isClientASteamDeck());
 	public OptionBoolean borderlessFullscreen = new OptionBoolean(this, "borderlessFullscreen", true);
 	public OptionBoolean startInFullscreen = new OptionBoolean(this, "startInFullscreen", true);
@@ -174,7 +177,14 @@ public class GameSettings {
 	public OptionBoolean enableHolidayTextures = new OptionBoolean(this, "enableHolidayTextures", true);
 	public OptionBoolean dynamicCursor = new OptionBoolean(this, "dynamicCursor", true);
 
-	public OptionBoolean playerLeftHanded = new OptionBoolean(this, "playerLeftHanded", false);
+	public OptionBoolean playerLeftHanded = new OptionBoolean(this, "player.left.handed", false);
+	public OptionBoolean playerCape = new OptionBoolean(this, "player.cape", true);
+	public OptionBoolean playerHat = new OptionBoolean(this, "player.hat", true);
+	public OptionBoolean playerJacket = new OptionBoolean(this, "player.jacket", true);
+	public OptionBoolean playerSleeveLeft = new OptionBoolean(this, "player.sleeve.left", true);
+	public OptionBoolean playerSleeveRight = new OptionBoolean(this, "player.sleeve.right", true);
+	public OptionBoolean playerPantLeft = new OptionBoolean(this, "player.pant.left", true);
+	public OptionBoolean playerPantRight = new OptionBoolean(this, "player.pant.right", true);
 
 	public KeyBinding keyAttack = new KeyBinding("key.attack").setDefault(InputDevice.mouse, 0);
 	public KeyBinding keyInteract = new KeyBinding("key.interact").setDefault(InputDevice.mouse, 1);
@@ -427,9 +437,16 @@ public class GameSettings {
 				mc.currentWorld.setDifficulty(difficulty.value, false);
 			}
 		}
-		if(option == playerLeftHanded && mc.thePlayer != null) {
-			mc.thePlayer.playerConfig.setLeftHand(playerLeftHanded.value);
-		}
+
+		if(option == playerLeftHanded && mc.thePlayer != null) {mc.thePlayer.playerConfig.setLeftHand(playerLeftHanded.value);}
+		if(option == playerCape && mc.thePlayer != null) {mc.thePlayer.playerConfig.setCape(playerCape.value);}
+		if(option == playerHat && mc.thePlayer != null) {mc.thePlayer.playerConfig.setHat(playerHat.value);}
+		if(option == playerJacket && mc.thePlayer != null) {mc.thePlayer.playerConfig.setJacket(playerJacket.value);}
+		if(option == playerSleeveLeft && mc.thePlayer != null) {mc.thePlayer.playerConfig.setSleeveLeft(playerSleeveLeft.value);}
+		if(option == playerSleeveRight && mc.thePlayer != null) {mc.thePlayer.playerConfig.setSleeveRight(playerSleeveRight.value);}
+		if(option == playerPantLeft && mc.thePlayer != null) {mc.thePlayer.playerConfig.setPantLeft(playerPantLeft.value);}
+		if(option == playerPantRight && mc.thePlayer != null) {mc.thePlayer.playerConfig.setPantRight(playerPantRight.value);}
+
 		if(option == enableVsync) mc.gameWindow.setVsync(enableVsync.value);
 		if(option == fancyGraphics) mc.renderGlobal.loadRenderers();
 		if(option == ambientOcclusion) mc.renderGlobal.loadRenderers();
@@ -443,6 +460,7 @@ public class GameSettings {
 		if(option == animations || option == customAnimations) {
 			mc.textureManager.refreshTexturesAndDisplayErrors();
 			mc.textureManager.updateDynamicTextures(false);
+			mc.renderGlobal.loadRenderers();
 		}
 		if(option == fullscreen) mc.gameWindow.updateWindowState();
 		if(option == borderlessFullscreen && fullscreen.value) mc.gameWindow.updateWindowState();
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 3f8597e1d..20ed62e9a 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
@@ -7,6 +7,7 @@ import static org.lwjgl.opengl.GL12.*;
 import java.awt.image.BufferedImage;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -47,6 +48,7 @@ import net.minecraft.client.util.helper.Textures;
 import net.minecraft.core.block.material.MaterialColor;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.Buffer;
+import net.minecraft.core.util.helper.DyeColor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
@@ -54,6 +56,11 @@ import org.slf4j.Logger;
 
 public class TextureManager {
 	private static final Logger LOGGER = LogUtils.getLogger();
+
+	public static final int ANIMATIONS_DISABLED = 0;
+	public static final int ANIMATIONS_NATIVE = 1;
+	public static final int ANIMATIONS_CUSTOM = 2;
+
 	public final Minecraft mc;
 
 	public final Map<Integer, Texture> idToTextureMap = new HashMap<>();
@@ -68,7 +75,7 @@ public class TextureManager {
 	private boolean clampTexture;
 	private boolean blurTexture;
 
-	public TextureManager(Minecraft minecraft, TexturePackList texturePacks, GameSettings gameSettings) {
+	public TextureManager(final Minecraft minecraft, final TexturePackList texturePacks, final GameSettings gameSettings) {
 		this.mc = minecraft;
 		
 		this.clampTexture = false;
@@ -78,35 +85,16 @@ public class TextureManager {
 		this.gameSettings = gameSettings;
 	}
 	
-	public void initDynamicTextures(List<Throwable> errors) {
+	public void initDynamicTextures(final Collection<? super Throwable> errors) {
 		LOGGER.info("Initializing Dynamic Textures...");
 
-		dynamicTextures.clear();
-
-		if (mc.gameSettings.animations.value != 0) {
-			boolean useCustomAnimations = mc.gameSettings.animations.value == 2;
+        this.dynamicTextures.clear();
 
+		addNativeDynamicTextures(this.mc.gameSettings.animations.value);
+		if (this.mc.gameSettings.customAnimations.value && this.mc.gameSettings.animations.value == ANIMATIONS_CUSTOM) {
 			try {
-                addDynamicTexture(new DynamicTextureWaterStill(TextureRegistry.getTexture("minecraft:block/water_still")));
-                addDynamicTexture(new DynamicTextureWaterFlow(TextureRegistry.getTexture("minecraft:block/water_flowing")));
-                addDynamicTexture(new DynamicTextureLavaStill(TextureRegistry.getTexture("minecraft:block/lava_still")));
-                addDynamicTexture(new DynamicTextureLavaFlowing(TextureRegistry.getTexture("minecraft:block/lava_flowing")));
-//                addDynamicTexture(new DynamicTexturePortal(TextureRegistry.getTexture("minecraft:block/portal_nether"),false));
-                addDynamicTexture(new DynamicTextureFire(TextureRegistry.getTexture("minecraft:block/fire"), false));
-				addDynamicTexture(new DynamicTextureFire(TextureRegistry.getTexture("minecraft:block/fire_cold"), true));
-
-                String[] fireflycolors = new String[] {"blue", "orange", "green", "red"};
-				for (String color : fireflycolors) {
-					addDynamicTexture(new DynamicTextureFireflyJar(TextureRegistry.getTexture("minecraft:block/lantern_firefly/" + color)));
-				}
-
-				addDynamicTexture(new DynamicTextureTrommel(mc, TextureRegistry.getTexture("minecraft:block/trommel/active_front"), true));
-				addDynamicTexture(new DynamicTextureTrommel(mc, TextureRegistry.getTexture("minecraft:block/trommel/active_back"), false));
-
-				if (useCustomAnimations) {
-					loadCustomAnimations();
-				}
-			}catch (TexturePackException e) {
+				loadCustomAnimations();
+			}catch (final TexturePackException e) {
 				errors.add(e);
 			}
 		}
@@ -116,6 +104,35 @@ public class TextureManager {
 		addDynamicTextureOverride(new DynamicTextureCompass(mc, TextureRegistry.getTexture("minecraft:item/tool_compass")), true);
 	}
 
+	protected void addNativeDynamicTextures(int state) {
+		if (state > ANIMATIONS_DISABLED) {addDynamicTexture(new DynamicTextureWaterStill(TextureRegistry.getTexture("minecraft:block/water_still")));
+			addDynamicTexture(new DynamicTextureWaterFlow(TextureRegistry.getTexture("minecraft:block/water_flowing")));
+			addDynamicTexture(new DynamicTextureLavaStill(TextureRegistry.getTexture("minecraft:block/lava_still")));
+			addDynamicTexture(new DynamicTextureLavaFlowing(TextureRegistry.getTexture("minecraft:block/lava_flowing")));
+            addDynamicTexture(new DynamicTextureFire(TextureRegistry.getTexture("minecraft:block/fire"), false));
+            addDynamicTexture(new DynamicTextureFire(TextureRegistry.getTexture("minecraft:block/fire_cold"), true));
+
+			final String[] fireflyColors = {"blue", "orange", "green", "red"};
+			for (final String color : fireflyColors) {
+				addDynamicTexture(new DynamicTextureFireflyJar(TextureRegistry.getTexture("minecraft:block/lantern_firefly/" + color)));
+			}
+
+			addDynamicTexture(new DynamicTextureTrommel(mc, TextureRegistry.getTexture("minecraft:block/trommel/active_front"), true));
+			addDynamicTexture(new DynamicTextureTrommel(mc, TextureRegistry.getTexture("minecraft:block/trommel/active_back"), false));
+		}
+		if (state < ANIMATIONS_CUSTOM) {
+			for (final DyeColor c : DyeColor.values()) {
+				final IconCoordinate cNether = TextureRegistry.getTexture("minecraft:block/portal_nether/" + c.colorID);
+				assert cNether.hasMeta("animation") : "Coordinate " + cNether.namespaceId + " is expected to have animation data attached!";
+				addDynamicTexture(new DynamicTextureCustom(cNether, cNether.getMeta("animation", AnimationProperties.class)));
+
+				final IconCoordinate cParadise = TextureRegistry.getTexture("minecraft:block/portal_paradise/" + c.colorID);
+				assert cParadise.hasMeta("animation") : "Coordinate " + cParadise.namespaceId + " is expected to have animation data attached!";
+				addDynamicTexture(new DynamicTextureCustom(cParadise, cParadise.getMeta("animation", AnimationProperties.class)));
+			}
+		}
+	}
+
 	protected void addDynamicTexture(DynamicTexture texture) {
 		addDynamicTextureOverride(texture, false);
 	}
@@ -125,12 +142,12 @@ public class TextureManager {
 	}
 
 	private void loadCustomAnimations() {
-		if(!mc.gameSettings.customAnimations.value) {
+		if(!this.mc.gameSettings.customAnimations.value) {
 			return;
 		}
 
-		for (AtlasStitcher stitcher : TextureRegistry.stitcherMap.values()){
-			for (IconCoordinate c : stitcher.textureMap.values()) {
+		for (final AtlasStitcher stitcher : TextureRegistry.stitcherMap.values()){
+			for (final IconCoordinate c : stitcher.textureMap.values()) {
 				if (c.hasMeta("animation")) {
                     LOGGER.debug("Icon '{}' has 'animation' meta!", c.namespaceId);
 					addDynamicTextureOverride(new DynamicTextureCustom(c, c.getMeta("animation", AnimationProperties.class)), true);
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 fa03f360a..a9ece6d4d 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
@@ -115,7 +115,7 @@ public class WorldRenderer
     private void updateSpeedFov()
     {
         PlayerLocal player = mc.thePlayer;
-        currentFovModifier = player.getFovModifier();
+        currentFovModifier = mc.gameSettings.fovModification.value ? player.getFovModifier() : 1f;
         a = b;
         b += (currentFovModifier - b) * 0.5f;
     }
@@ -316,44 +316,44 @@ public class WorldRenderer
         }
     }
 
-    private void setupCameraTransform(float partialTick)
+    private void setupCameraTransform(final float partialTicks)
     {
-        farPlaneDistance = mc.gameSettings.renderDistance.value * 16;
+        this.farPlaneDistance = this.mc.gameSettings.renderDistance.value * 16;
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
-        float fov = getFOVModifier(partialTick, true);
-        if(zooming) {
-            fov = getZoomedFOV(fov, partialTick);
+        float fov = getFOVModifier(partialTicks, true);
+        if(this.zooming) {
+            fov = getZoomedFOV(fov, partialTicks);
         } else {
-            zoomProgress = 0;
+            this.zoomProgress = 0;
         }
-        if (mc.currentScreen instanceof ScreenPhotoMode)
+        if (this.mc.currentScreen instanceof ScreenPhotoMode)
         {
-            double div = java.lang.Math.pow(2, ((ScreenPhotoMode)mc.currentScreen).getZoom(partialTick));
+            final double div = java.lang.Math.pow(2, ((ScreenPhotoMode) this.mc.currentScreen).getZoom(partialTicks));
             glTranslatef(1, 1, 0);
-            glOrtho(0, mc.gameWindow.getWidthPixels() / div, 0, mc.gameWindow.getHeightPixels() / div, farPlaneDistance * -2.0f, farPlaneDistance * 2.0f);
-            glTranslatef(((ScreenPhotoMode)mc.currentScreen).getPanX(partialTick), -((ScreenPhotoMode)mc.currentScreen).getPanY(partialTick), 0);
+            glOrtho(0, this.mc.gameWindow.getWidthPixels() / div, 0, this.mc.gameWindow.getHeightPixels() / div, this.farPlaneDistance * -2.0f, this.farPlaneDistance * 2.0f);
+            glTranslatef(((ScreenPhotoMode) this.mc.currentScreen).getPanX(partialTicks), -((ScreenPhotoMode) this.mc.currentScreen).getPanY(partialTicks), 0);
         } else
         {
-            GLU.gluPerspective(fov, (float)mc.gameWindow.getWidthPixels() / (float)mc.gameWindow.getHeightPixels(), 0.05F, farPlaneDistance * 2.0F);
+            GLU.gluPerspective(fov, (float) this.mc.gameWindow.getWidthPixels() / (float) this.mc.gameWindow.getHeightPixels(), 0.05F, this.farPlaneDistance * 2.0F);
         }
         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
-        hurtCameraEffect(partialTick);
-        if(mc.gameSettings.viewBobbing.value && !(mc.currentScreen instanceof ScreenPhotoMode))
+        hurtCameraEffect(partialTicks);
+        if(this.mc.gameSettings.viewBobbing.value && !(this.mc.currentScreen instanceof ScreenPhotoMode))
         {
-            setupViewBobbing(partialTick);
+            setupViewBobbing(partialTicks);
         }
-        float f2 = mc.thePlayer.prevTimeInPortal + (mc.thePlayer.timeInPortal - mc.thePlayer.prevTimeInPortal) * partialTick;
-        if(f2 > 0.0F)
+        final float portalIntensity = this.mc.gameSettings.screenMotionEffects.value ? MathHelper.lerp(this.mc.thePlayer.prevTimeInPortal, this.mc.thePlayer.timeInPortal, partialTicks) : 0f;
+        if(portalIntensity > 0.0F)
         {
-            float f3 = 5F / (f2 * f2 + 5F) - f2 * 0.04F;
+            float f3 = 5F / (portalIntensity * portalIntensity + 5F) - portalIntensity * 0.04F;
             f3 *= f3;
-            glRotatef(((float)rendererUpdateCount + partialTick) * 20F, 0.0F, 1.0F, 1.0F);
+            glRotatef(((float) this.rendererUpdateCount + partialTicks) * 20F, 0.0F, 1.0F, 1.0F);
             glScalef(1.0F / f3, 1.0F, 1.0F);
-            glRotatef(-((float)rendererUpdateCount + partialTick) * 20F, 0.0F, 1.0F, 1.0F);
+            glRotatef(-((float) this.rendererUpdateCount + partialTicks) * 20F, 0.0F, 1.0F, 1.0F);
         }
-        orientCamera(partialTick);
+        orientCamera(partialTicks);
     }
 
     private void renderHand(float partialTick)
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java
index db740a5af..89295e750 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java
@@ -186,6 +186,6 @@ public class DynamicTextureCustom extends DynamicTexture {
 	}
 	@Override
 	public boolean runUpdates(boolean isPaused) {
-		return (!isPaused || tickWhenPaused);
+		return mc.gameSettings.animations.value != 0 && (!isPaused || tickWhenPaused);
 	}
 }
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 72f55827f..5ef2d7207 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
@@ -202,39 +202,41 @@ public class MobRendererPlayer extends MobRendererBipedArmored<Player>
 
         super.renderAdditional(player, partialTick);
 
-        boolean renderCape = bindDownloadableTexture("https://api.betterthanadventure.net/capes?username=" + player.username, null, null);
-        if (!renderCape)
-        {
-            renderCape = bindDownloadableTexture(player.capeURL, null, null);
-        }
-
-        if(renderCape) {
-            GL11.glPushMatrix();
-            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;
-            if(player.isSneaking())
+        if (player.playerConfig.capeEnabled()) {
+            boolean renderCape = bindDownloadableTexture("https://api.betterthanadventure.net/capes?username=" + player.username, null, null);
+            if (!renderCape)
             {
-                bodyAngle += 25F;
+                renderCape = bindDownloadableTexture(player.capeURL, null, null);
+            }
+
+            if(renderCape) {
+                GL11.glPushMatrix();
+                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;
+                if(player.isSneaking())
+                {
+                    bodyAngle += 25F;
+                }
+                double _xd = player.xdO + (player.xd - player.xdO) * partialTick;
+                double _yd = Math.min(player.ydO + (player.yd - player.ydO) * partialTick, 0);
+                double _zd = player.zd0 + (player.zd - player.zd0) * partialTick;
+                double vel = -1/(3 * Math.hypot(_xd, _zd) + 1) + 1;
+                double moveAng = Math.atan2(_xd, _zd);
+                double yawRad = Math.toRadians(yawOff);
+                double multiplier = 1 - Math.abs((((Math.cos(yawRad) + 1) - (Math.cos(moveAng) + 1) + 2)/2) -1); // Hell code, basically measures how similar the angle you're facing is to the angle you're moving, with it returning 1 if the same angle and 0 if opposite angles
+                player.wobbleTimer += (float) (((player.tickCount + partialTick) - player.lastRenderTick)/(30 - 29 * MathHelper.clamp(vel, 0, 1)));
+                player.lastRenderTick = player.tickCount;
+                double wobble = Math.sin(player.wobbleTimer) * (1.5 + 4.5 * vel * multiplier);
+                GL11.glRotatef((float) MathHelper.clamp((MathHelper.clamp(bodyAngle + vel * 100 * multiplier, bodyAngle, 100f) + wobble) - _yd * 60, 0, 180), 1.0F, 0.0F, 0.0F);
+                GL11.glRotatef(0, 0.0F, 0.0F, 1.0F);
+                GL11.glRotatef(0, 0.0F, 1.0F, 0.0F);
+                GL11.glRotatef(180F, 0.0F, 1.0F, 0.0F);
+                modelBipedMain.renderCloak(0.0625F);
+                GL11.glPopMatrix();
             }
-            double _xd = player.xdO + (player.xd - player.xdO) * partialTick;
-            double _yd = Math.min(player.ydO + (player.yd - player.ydO) * partialTick, 0);
-            double _zd = player.zd0 + (player.zd - player.zd0) * partialTick;
-            double vel = -1/(3 * Math.hypot(_xd, _zd) + 1) + 1;
-            double moveAng = Math.atan2(_xd, _zd);
-            double yawRad = Math.toRadians(yawOff);
-            double multiplier = 1 - Math.abs((((Math.cos(yawRad) + 1) - (Math.cos(moveAng) + 1) + 2)/2) -1); // Hell code, basically measures how similar the angle you're facing is to the angle you're moving, with it returning 1 if the same angle and 0 if opposite angles
-            player.wobbleTimer += (float) (((player.tickCount + partialTick) - player.lastRenderTick)/(30 - 29 * MathHelper.clamp(vel, 0, 1)));
-            player.lastRenderTick = player.tickCount;
-            double wobble = Math.sin(player.wobbleTimer) * (1.5 + 4.5 * vel * multiplier);
-            GL11.glRotatef((float) MathHelper.clamp((MathHelper.clamp(bodyAngle + vel * 100 * multiplier, bodyAngle, 100f) + wobble) - _yd * 60, 0, 180), 1.0F, 0.0F, 0.0F);
-            GL11.glRotatef(0, 0.0F, 0.0F, 1.0F);
-            GL11.glRotatef(0, 0.0F, 1.0F, 0.0F);
-            GL11.glRotatef(180F, 0.0F, 1.0F, 0.0F);
-            modelBipedMain.renderCloak(0.0625F);
-            GL11.glPopMatrix();
         }
 
         if (player.getHeldObject() != null) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayer.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayer.java
index 4a8a0aa1b..70903946e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayer.java
@@ -1,6 +1,7 @@
 package net.minecraft.client.render.model;
 
 import net.minecraft.core.entity.Mob;
+import net.minecraft.core.entity.player.Player;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
@@ -64,14 +65,34 @@ public class ModelPlayer extends ModelBiped {
 
     @Override
 	public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick){
-        super.render(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        GL11.glPushMatrix();
-        bipedLeftArmOverlay.render(scale);
-        bipedRightArmOverlay.render(scale);
-        bipedLeftLegOverlay.render(scale);
-        bipedRightLegOverlay.render(scale);
-        bipedBodyOverlay.render(scale);
-        GL11.glPopMatrix();
+        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
+        head.render(scale);
+        body.render(scale);
+        armRight.render(scale);
+        armLeft.render(scale);
+        legRight.render(scale);
+        legLeft.render(scale);
+        if (mob instanceof Player) {
+            Player player = (Player) mob;
+            if (player.playerConfig.hatEnabled()) hair.render(scale);
+            GL11.glPushMatrix();
+            if (player.playerConfig.sleeveLeftEnabled()) bipedLeftArmOverlay.render(scale);
+            if (player.playerConfig.sleeveRightEnabled()) bipedRightArmOverlay.render(scale);
+            if (player.playerConfig.pantLeftEnabled()) bipedLeftLegOverlay.render(scale);
+            if (player.playerConfig.pantRightEnabled()) bipedRightLegOverlay.render(scale);
+            if (player.playerConfig.jacketEnabled()) bipedBodyOverlay.render(scale);
+            GL11.glPopMatrix();
+        } else {
+            hair.render(scale);
+            GL11.glPushMatrix();
+            bipedLeftArmOverlay.render(scale);
+            bipedRightArmOverlay.render(scale);
+            bipedLeftLegOverlay.render(scale);
+            bipedRightLegOverlay.render(scale);
+            bipedBodyOverlay.render(scale);
+            GL11.glPopMatrix();
+        }
+
     }
 
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java
index 14ef09aa1..1d9ab4b49 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java
@@ -48,7 +48,7 @@ public abstract class TexturePack {
 	{
 		if (Holidays.getCurrentThemedHoliday() != null && Minecraft.getMinecraft().gameSettings.enableHolidayTextures.value) {
 			assert Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() != null : "Current themed holiday must have a theme!";
-			String holidayPath = ("/holidays/" + Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() + "/" + s);
+			String holidayPath = ("/holidays/" + Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() + "/" + s).replace("//", "/");
 			InputStream holidayStream = TexturePack.class.getResourceAsStream(holidayPath);
 			if (holidayStream != null) return holidayStream;
 		}
diff --git a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackCustom.java b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackCustom.java
index 622bd99e6..276f0eb0c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackCustom.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackCustom.java
@@ -192,7 +192,7 @@ public class TexturePackCustom extends TexturePack
 	{
 		if (firstCall && Holidays.getCurrentThemedHoliday() != null && Minecraft.getMinecraft().gameSettings.enableHolidayTextures.value) {
 			assert Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() != null : "Current themed holiday must have a theme!";
-			String holidayPath = ("/holidays/" + Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() + "/" + path);
+			String holidayPath = ("/holidays/" + Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() + "/" + path).replace("//", "/");
 			InputStream holidayStream = getResourceAsStream(holidayPath, false);
 			if (holidayStream != null) return holidayStream;
 		}
diff --git a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackDefault.java b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackDefault.java
index dd90eff40..a02869ba9 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackDefault.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackDefault.java
@@ -69,7 +69,7 @@ public class TexturePackDefault extends TexturePack
                 return true;
             } else if (Minecraft.getMinecraft().gameSettings.enableHolidayTextures.value && Holidays.getCurrentThemedHoliday() != null) {
                 assert Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() != null : "Current themed holiday must have a theme!";
-                String holidayPath = ("/holidays/" + Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() + "/" + file);
+                String holidayPath = ("/holidays/" + Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() + "/" + file).replace("//", "/");
                 InputStream holidayStream = TexturePack.class.getResourceAsStream(holidayPath);
                 if (holidayStream != null) {
                     holidayStream.close();
diff --git a/game/client/src/main/resources/holidays/xmas/assets/minecraft/textures/entity/wolf_angry/0.png b/game/client/src/main/resources/holidays/xmas/assets/minecraft/textures/entity/wolf_angry/0.png
new file mode 100644
index 000000000..89b3d2d6a
Binary files /dev/null and b/game/client/src/main/resources/holidays/xmas/assets/minecraft/textures/entity/wolf_angry/0.png differ
diff --git a/game/client/src/main/resources/holidays/xmas/assets/minecraft/textures/entity/wolf_angry/1.png b/game/client/src/main/resources/holidays/xmas/assets/minecraft/textures/entity/wolf_angry/1.png
new file mode 100644
index 000000000..89b3d2d6a
Binary files /dev/null and b/game/client/src/main/resources/holidays/xmas/assets/minecraft/textures/entity/wolf_angry/1.png differ
diff --git a/game/client/src/main/resources/holidays/xmas/assets/minecraft/textures/entity/wolf_tame/variants.json b/game/client/src/main/resources/holidays/xmas/assets/minecraft/textures/entity/wolf_tame/variants.json
deleted file mode 100644
index e610d1df0..000000000
--- a/game/client/src/main/resources/holidays/xmas/assets/minecraft/textures/entity/wolf_tame/variants.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-    "skins": 2
-}
\ No newline at end of file
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 22d4b469a..1772a1c40 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
@@ -48,7 +48,7 @@ public class BlockLogicFlag extends BlockLogic {
         if (tileEntity != null)
         {
             CompoundTag compound = new CompoundTag();
-            ((TileEntityFlag) tileEntity).writeFlagNBT(compound);
+            tileEntity.writeAdditionalData(compound);
             stack.getData().putCompound("FlagData", compound);
         }
         return new ItemStack[] { stack };
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCherry.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCherry.java
index 9fd501014..3a7bb6031 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCherry.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingCherry.java
@@ -4,6 +4,7 @@ import java.util.Random;
 
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.generate.feature.WorldFeature;
+import net.minecraft.core.world.generate.feature.tree.WorldFeatureCherryTreeFancy;
 import net.minecraft.core.world.generate.feature.tree.WorldFeatureTreeCherry;
 import net.minecraft.core.world.generate.feature.tree.WorldFeatureTreeFancy;
 
@@ -18,7 +19,7 @@ public class BlockLogicSaplingCherry extends BlockLogicSaplingBase
     @Override
 	public void growTree(World world, int x, int y, int z, Random random)
     {
-        WorldFeature treeBig  = new WorldFeatureTreeFancy(Blocks.LEAVES_CHERRY.id(), Blocks.LOG_CHERRY.id());
+        WorldFeature treeBig  = new WorldFeatureCherryTreeFancy(Blocks.LEAVES_CHERRY.id(), Blocks.LOG_CHERRY.id());
         WorldFeature treeSmall = new WorldFeatureTreeCherry(Blocks.LEAVES_CHERRY.id(), Blocks.LOG_CHERRY.id(), 4);
         world.setBlock(x, y, z, 0);
 
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 ecbc1c78a..a6ea92d5a 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
@@ -13,9 +13,10 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.ICarriable;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class TileEntity implements ICarriable
+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;
@@ -94,14 +95,17 @@ public class TileEntity implements ICarriable
         tileEntityInvalid = false;
     }
 
-    public void readFromNBT(CompoundTag nbttagcompound)
+    public final void readFromNBT(@NotNull CompoundTag compoundTag)
     {
-        x = nbttagcompound.getInteger("x");
-        y = nbttagcompound.getInteger("y");
-        z = nbttagcompound.getInteger("z");
+        x = compoundTag.getInteger("x");
+        y = compoundTag.getInteger("y");
+        z = compoundTag.getInteger("z");
+        readAdditionalData(compoundTag);
     }
 
-    public void writeToNBT(CompoundTag nbttagcompound)
+    public abstract void readAdditionalData(@NotNull CompoundTag compoundTag);
+
+    public final void writeToNBT(@NotNull CompoundTag compoundTag)
     {
         NamespaceID name = TileEntityDispatcher.getIDFromClass(getClass());
         if(name == null)
@@ -109,13 +113,16 @@ public class TileEntity implements ICarriable
             throw new RuntimeException(getClass() + " is missing a mapping! This is a bug!");
         } else
         {
-            nbttagcompound.putString("id", name.toString());
-            nbttagcompound.putInt("x", x);
-            nbttagcompound.putInt("y", y);
-            nbttagcompound.putInt("z", z);
+            compoundTag.putString("id", name.toString());
+            compoundTag.putInt("x", x);
+            compoundTag.putInt("y", y);
+            compoundTag.putInt("z", z);
+            writeAdditionalData(compoundTag);
         }
     }
 
+    public abstract void writeAdditionalData(@NotNull CompoundTag compoundTag);
+
     @Override
     public void heldTick(World world, Entity holder) {
 
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 cdcd2ebd8..5b20fdef6 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
@@ -12,6 +12,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Random;
 
@@ -135,9 +136,8 @@ public class TileEntityActivator extends TileEntity implements Container {
     }
 
     @Override
-    public void readFromNBT(CompoundTag compoundTag)
+    public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.readFromNBT(compoundTag);
         stackSelector = compoundTag.getByte("Selector");
         lockedSlotBitSet = compoundTag.getShort("LockedSlots");
         ListTag itemListTag = compoundTag.getList("Items");
@@ -155,9 +155,8 @@ public class TileEntityActivator extends TileEntity implements Container {
     }
 
     @Override
-    public void writeToNBT(CompoundTag compoundTag)
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(compoundTag);
         compoundTag.putByte("Selector", (byte) stackSelector);
         compoundTag.putShort("LockedSlots", lockedSlotBitSet);
         ListTag itemListTag = new ListTag();
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 13e4abeb3..f0e75173d 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
@@ -14,6 +14,7 @@ import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.PacketTileEntityData;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 
 public class TileEntityBasket extends TileEntity
 {
@@ -103,10 +104,8 @@ public class TileEntityBasket extends TileEntity
 	}
 
     @Override
-    public void readFromNBT(final CompoundTag tag)
-    {
-        super.readFromNBT(tag);
-        final ListTag itemsTag = tag.getList("Items");
+    public void readAdditionalData(@NotNull CompoundTag compoundTag) {
+        final ListTag itemsTag = compoundTag.getList("Items");
         contents.clear();
         for (int i = 0; i < itemsTag.tagCount(); i++)
         {
@@ -186,9 +185,8 @@ public class TileEntityBasket extends TileEntity
     }
 
     @Override
-    public void writeToNBT(final CompoundTag tag)
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(tag);
         final ListTag itemsTag = new ListTag();
         for (Map.Entry<BasketEntry, Integer> entry : contents.entrySet())
         {
@@ -198,7 +196,7 @@ public class TileEntityBasket extends TileEntity
             itemsTag.addTag(itemTag);
         }
 
-        tag.put("Items", itemsTag);
+        compoundTag.put("Items", itemsTag);
     }
 
     @Override
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 3c7504611..e1555e48e 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
@@ -14,6 +14,7 @@ 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;
+import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 
 public class TileEntityChest extends TileEntity
@@ -81,10 +82,9 @@ public class TileEntityChest extends TileEntity
     }
 
     @Override
-	public void readFromNBT(CompoundTag nbttagcompound)
+    public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.readFromNBT(nbttagcompound);
-        ListTag nbttaglist = nbttagcompound.getList("Items");
+        ListTag nbttaglist = compoundTag.getList("Items");
         chestContents = new ItemStack[getContainerSize()];
         for(int i = 0; i < nbttaglist.tagCount(); i++)
         {
@@ -98,9 +98,8 @@ public class TileEntityChest extends TileEntity
     }
 
     @Override
-	public void writeToNBT(CompoundTag nbttagcompound)
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(nbttagcompound);
         ListTag nbttaglist = new ListTag();
         for(int i = 0; i < chestContents.length; i++)
         {
@@ -113,7 +112,7 @@ public class TileEntityChest extends TileEntity
             }
         }
 
-        nbttagcompound.put("Items", nbttaglist);
+        compoundTag.put("Items", nbttaglist);
     }
 
     @Override
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 cb993fea7..d36da668a 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
@@ -13,6 +13,7 @@ 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;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Random;
 
@@ -112,10 +113,9 @@ public class TileEntityDispenser extends TileEntity
     }
 
     @Override
-	public void readFromNBT(CompoundTag nbttagcompound)
+	public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.readFromNBT(nbttagcompound);
-        ListTag nbttaglist = nbttagcompound.getList("Items");
+        ListTag nbttaglist = compoundTag.getList("Items");
         dispenserContents = new ItemStack[getContainerSize()];
         for(int i = 0; i < nbttaglist.tagCount(); i++)
         {
@@ -130,9 +130,8 @@ public class TileEntityDispenser extends TileEntity
     }
 
     @Override
-	public void writeToNBT(CompoundTag nbttagcompound)
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(nbttagcompound);
         ListTag nbttaglist = new ListTag();
         for(int i = 0; i < dispenserContents.length; i++)
         {
@@ -145,7 +144,7 @@ public class TileEntityDispenser extends TileEntity
             }
         }
 
-        nbttagcompound.put("Items", nbttaglist);
+        compoundTag.put("Items", nbttaglist);
     }
 
     @Override
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 e28a08896..9aab9595a 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
@@ -13,6 +13,7 @@ import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.PacketTileEntityData;
 import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.util.helper.UUIDHelper;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class TileEntityFlag extends TileEntity
@@ -74,17 +75,11 @@ public class TileEntityFlag extends TileEntity
     }
 
     @Override
-    public void writeToNBT(CompoundTag tag) {
-        super.writeToNBT(tag);
-        writeFlagNBT(tag);
-    }
-    
-    public void writeFlagNBT(CompoundTag tag)
-    {
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag) {
         byte[] packedColors = packFlagColors(flagColors);
-        tag.putByteArray("Colors", packedColors);
-        UUIDHelper.writeToTag(tag, owner, "OwnerUUID");
-        tag.putBoolean("Flip", flipped);
+        compoundTag.putByteArray("Colors", packedColors);
+        UUIDHelper.writeToTag(compoundTag, owner, "OwnerUUID");
+        compoundTag.putBoolean("Flip", flipped);
 
         ListTag list = new ListTag();
         for (int i = 0; i < items.length; i++)
@@ -97,19 +92,13 @@ public class TileEntityFlag extends TileEntity
                 list.addTag(compound);
             }
         }
-        tag.putList("Items", list);
+        compoundTag.putList("Items", list);
     }
 
     @Override
-    public void readFromNBT(CompoundTag tag)
-    {
-        super.readFromNBT(tag);
-        readFlagNBT(tag);
-    }
-    
-    public void readFlagNBT(CompoundTag tag)
+    public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        byte[] packedColors = tag.getByteArrayOrDefault("Colors", null);
+        byte[] packedColors = compoundTag.getByteArrayOrDefault("Colors", null);
         if (packedColors == null) packedColors = new byte[(CANVAS_WIDTH * CANVAS_HEIGHT) / 4];
         byte[] unpackedColors = unpackFlagColors(packedColors);
         System.arraycopy(unpackedColors, 0, flagColors, 0, CANVAS_WIDTH * CANVAS_HEIGHT);
@@ -119,9 +108,9 @@ public class TileEntityFlag extends TileEntity
             colorHash ^= flagColors[i] << (8 * (i & 0b11));
         }
 
-        UUID ownerUUID = UUIDHelper.readFromTag(tag, "OwnerUUID");
+        UUID ownerUUID = UUIDHelper.readFromTag(compoundTag, "OwnerUUID");
         if (ownerUUID == null) {
-            String s = tag.getString("Owner");
+            String s = compoundTag.getString("Owner");
             if (!s.isEmpty()) {
                 UUIDHelper.runConversionAction(s,
                     (uuid) -> this.owner = uuid,
@@ -131,9 +120,9 @@ public class TileEntityFlag extends TileEntity
             this.owner = ownerUUID;
         }
 
-        flipped = tag.getBooleanOrDefault("Flip", false);
+        flipped = compoundTag.getBooleanOrDefault("Flip", false);
 
-        ListTag list = tag.getList("Items");
+        ListTag list = compoundTag.getList("Items");
         items = new ItemStack[getContainerSize()];
         for (int i = 0; i < list.tagCount(); i++)
         {
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 6b1995c3a..2f86a3967 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
@@ -9,6 +9,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.PacketTileEntityData;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 
 public class TileEntityFlowerJar extends TileEntity {
 
@@ -16,18 +17,16 @@ public class TileEntityFlowerJar extends TileEntity {
     public int flowerData;
 
     @Override
-    public void readFromNBT(CompoundTag tag) {
-        super.readFromNBT(tag);
-        flowerInPot = tag.getInteger("PlantedId");
-        flowerData = Byte.toUnsignedInt(tag.getByteOrDefault("PlantedData", (byte) 0));
+    public void readAdditionalData(@NotNull CompoundTag compoundTag) {
+        flowerInPot = compoundTag.getInteger("PlantedId");
+        flowerData = Byte.toUnsignedInt(compoundTag.getByteOrDefault("PlantedData", (byte) 0));
     }
 
     @Override
-    public void writeToNBT(CompoundTag tag) {
-        super.writeToNBT(tag);
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag) {
         if (flowerInPot > 0) {
-            tag.putInt("PlantedId", flowerInPot);
-            tag.putByte("PlantedData", (byte) flowerData);
+            compoundTag.putInt("PlantedId", flowerInPot);
+            compoundTag.putByte("PlantedData", (byte) flowerData);
         }
     }
 
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 154efaccd..2793f0879 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
@@ -19,6 +19,7 @@ import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.List;
 import java.util.Random;
@@ -99,10 +100,9 @@ public class TileEntityFurnace extends TileEntity
     }
 
     @Override
-	public void readFromNBT(CompoundTag nbttagcompound)
+	public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.readFromNBT(nbttagcompound);
-        ListTag nbttaglist = nbttagcompound.getList("Items");
+        ListTag nbttaglist = compoundTag.getList("Items");
         furnaceItemStacks = new ItemStack[getContainerSize()];
         for(int i = 0; i < nbttaglist.tagCount(); i++)
         {
@@ -114,18 +114,17 @@ public class TileEntityFurnace extends TileEntity
             }
         }
 
-        currentBurnTime = nbttagcompound.getShort("BurnTime");
-        currentCookTime = nbttagcompound.getShort("CookTime");
-        maxBurnTime = nbttagcompound.getShort("MaxBurnTime");
+        currentBurnTime = compoundTag.getShort("BurnTime");
+        currentCookTime = compoundTag.getShort("CookTime");
+        maxBurnTime = compoundTag.getShort("MaxBurnTime");
     }
 
     @Override
-	public void writeToNBT(CompoundTag nbttagcompound)
+	public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(nbttagcompound);
-        nbttagcompound.putShort("BurnTime", (short) currentBurnTime);
-        nbttagcompound.putShort("CookTime", (short) currentCookTime);
-        nbttagcompound.putShort("MaxBurnTime", (short) maxBurnTime);
+        compoundTag.putShort("BurnTime", (short) currentBurnTime);
+        compoundTag.putShort("CookTime", (short) currentCookTime);
+        compoundTag.putShort("MaxBurnTime", (short) maxBurnTime);
         ListTag nbttaglist = new ListTag();
         for(int i = 0; i < furnaceItemStacks.length; i++)
         {
@@ -138,7 +137,7 @@ public class TileEntityFurnace extends TileEntity
             }
         }
 
-        nbttagcompound.put("Items", nbttaglist);
+        compoundTag.put("Items", nbttaglist);
     }
 
     @Override
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 44f078335..07e248c08 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
@@ -9,6 +9,7 @@ import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.data.registry.recipe.entry.RecipeEntryBlastFurnace;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.container.Container;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.List;
 
@@ -29,49 +30,6 @@ public class TileEntityFurnaceBlast extends TileEntityFurnace
         return "container.furnace_blast.name";
     }
 
-    @Override
-	public void readFromNBT(CompoundTag nbttagcompound)
-    {
-        super.readFromNBT(nbttagcompound);
-        ListTag nbttaglist = nbttagcompound.getList("Items");
-        furnaceItemStacks = new ItemStack[getContainerSize()];
-        for(int i = 0; i < nbttaglist.tagCount(); i++)
-        {
-            CompoundTag nbttagcompound1 = (CompoundTag)nbttaglist.tagAt(i);
-            byte byte0 = nbttagcompound1.getByte("Slot");
-            if(byte0 >= 0 && byte0 < furnaceItemStacks.length)
-            {
-                furnaceItemStacks[byte0] = ItemStack.readItemStackFromNbt(nbttagcompound1);
-            }
-        }
-
-        currentBurnTime = nbttagcompound.getShort("BurnTime");
-        currentCookTime = nbttagcompound.getShort("CookTime");
-        maxBurnTime = nbttagcompound.getShort("MaxBurnTime");
-    }
-
-    @Override
-	public void writeToNBT(CompoundTag nbttagcompound)
-    {
-        super.writeToNBT(nbttagcompound);
-        nbttagcompound.putShort("BurnTime", (short) currentBurnTime);
-        nbttagcompound.putShort("CookTime", (short) currentCookTime);
-        nbttagcompound.putShort("MaxBurnTime", (short) maxBurnTime);
-        ListTag nbttaglist = new ListTag();
-        for(int i = 0; i < furnaceItemStacks.length; i++)
-        {
-            if(furnaceItemStacks[i] != null)
-            {
-                CompoundTag itemStackAtSlot = new CompoundTag();
-                itemStackAtSlot.putByte("Slot", (byte)i);
-                furnaceItemStacks[i].writeToNBT(itemStackAtSlot);
-                nbttaglist.addTag(itemStackAtSlot);
-            }
-        }
-
-        nbttagcompound.put("Items", nbttaglist);
-    }
-
     @Override
 	public void tick()
     {
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityJarButterfly.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityJarButterfly.java
index b7f10d695..77121d8e1 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityJarButterfly.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityJarButterfly.java
@@ -2,6 +2,7 @@ package net.minecraft.core.block.entity;
 
 import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.entity.animal.MobButterfly;
+import org.jetbrains.annotations.NotNull;
 
 public class TileEntityJarButterfly extends TileEntity{
     public MobButterfly.ButterflyEntry color;
@@ -25,14 +26,12 @@ public class TileEntityJarButterfly extends TileEntity{
     }
 
     @Override
-    public void readFromNBT(CompoundTag compoundTag) {
-        super.readFromNBT(compoundTag);
+    public void readAdditionalData(@NotNull CompoundTag compoundTag) {
         color = MobButterfly.colorEntries.getOrDefault(compoundTag.getByte("color") & 0xFF, MobButterfly.COLOR_BLUE);
     }
 
     @Override
-    public void writeToNBT(CompoundTag compoundTag) {
-        super.writeToNBT(compoundTag);
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag) {
         compoundTag.putByte("color", (byte) color.id);
     }
 }
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 899b505d3..8151eceaf 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
@@ -7,6 +7,7 @@ import net.minecraft.core.world.LevelListener;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.save.conversion.ChunkConverter;
 import com.mojang.nbt.tags.CompoundTag;
+import org.jetbrains.annotations.NotNull;
 
 public class TileEntityJukebox extends TileEntity {
     public int record;
@@ -14,10 +15,9 @@ public class TileEntityJukebox extends TileEntity {
     }
 
     @Override
-	public void readFromNBT(CompoundTag nbttagcompound) {
-        super.readFromNBT(nbttagcompound);
-        record = nbttagcompound.getInteger("Record");
-        byte expanded = nbttagcompound.getByte("Expanded");
+    public void readAdditionalData(@NotNull CompoundTag compoundTag) {
+        record = compoundTag.getInteger("Record");
+        byte expanded = compoundTag.getByte("Expanded");
         if (expanded == 0 && record >= 256) {
             record += (Blocks.blocksList.length - 256);
         }
@@ -30,11 +30,10 @@ public class TileEntityJukebox extends TileEntity {
     }
 
     @Override
-	public void writeToNBT(CompoundTag nbttagcompound) {
-        super.writeToNBT(nbttagcompound);
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag) {
         if (record > 0) {
-            nbttagcompound.putInt("Record", record);
-            nbttagcompound.putByte("Expanded", (byte) 1);
+            compoundTag.putInt("Record", record);
+            compoundTag.putByte("Expanded", (byte) 1);
         }
     }
 
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 9e1882d97..c31b65acb 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
@@ -7,6 +7,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.PacketTileEntityData;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class TileEntityMeshGold extends TileEntity {
@@ -45,9 +46,8 @@ public class TileEntityMeshGold extends TileEntity {
         return success | !wasNull;
     }
     @Override
-    public void readFromNBT(CompoundTag compoundTag)
+    public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.readFromNBT(compoundTag);
         if (compoundTag.getBoolean("hasItem")){
             filterItem = ItemStack.readItemStackFromNbt(compoundTag.getCompound("item"));
         } else {
@@ -56,9 +56,8 @@ public class TileEntityMeshGold extends TileEntity {
     }
 
     @Override
-    public void writeToNBT(CompoundTag compoundTag)
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(compoundTag);
         if (filterItem != null){
             compoundTag.putCompound("item", filterItem.writeToNBT(new CompoundTag()));
             compoundTag.putBoolean("hasItem", true);
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 ff1e5da00..79bd83c8b 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
@@ -8,6 +8,7 @@ import net.minecraft.core.util.phys.AABB;
 import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.PacketSetMobSpawner;
+import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 
 public class TileEntityMobSpawner extends TileEntity
@@ -171,19 +172,17 @@ public class TileEntityMobSpawner extends TileEntity
     }
 
     @Override
-	public void readFromNBT(CompoundTag tag)
+    public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.readFromNBT(tag);
-        setMobId(tag.getString("EntityId"));
-        delay = tag.getShort("Delay");
+        setMobId(compoundTag.getString("EntityId"));
+        delay = compoundTag.getShort("Delay");
     }
 
     @Override
-	public void writeToNBT(CompoundTag tag)
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(tag);
-        tag.putString("EntityId", mobId != null ? mobId : "none");
-        tag.putShort("Delay", (short)delay);
+        compoundTag.putString("EntityId", mobId != null ? mobId : "none");
+        compoundTag.putShort("Delay", (short)delay);
     }
 
 }
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 df4e9b66d..29dfd3d60 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
@@ -4,6 +4,7 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.BlockLogicNote;
 import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
 
 @Deprecated
 public class TileEntityNoteblock extends TileEntity
@@ -25,15 +26,13 @@ public class TileEntityNoteblock extends TileEntity
     }
 
     @Override
-	public void writeToNBT(CompoundTag tag) {
-        super.writeToNBT(tag);
-        tag.putByte("note", note);
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag) {
+        compoundTag.putByte("note", note);
     }
 
     @Override
-	public void readFromNBT(CompoundTag tag) {
-        super.readFromNBT(tag);
-        note = MathHelper.clamp(tag.getByte("note"), (byte) 0, BlockLogicNote.MAX_NOTE);
+    public void readAdditionalData(@NotNull CompoundTag compoundTag) {
+        note = MathHelper.clamp(compoundTag.getByte("note"), (byte) 0, BlockLogicNote.MAX_NOTE);
     }
 
 }
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 62d64220e..c89a1f0d9 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
@@ -7,6 +7,7 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.IVehicle;
 import net.minecraft.core.world.World;
 import com.mojang.nbt.tags.CompoundTag;
+import org.jetbrains.annotations.NotNull;
 
 public class TileEntitySeat
     extends TileEntity
@@ -138,18 +139,16 @@ public class TileEntitySeat
     }
 
     @Override
-    public void writeToNBT(CompoundTag compoundTag)
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(compoundTag);
         if (seat != null && seat != Blocks.SEAT) {
             compoundTag.putInt("Block", seat.id());
         }
     }
 
     @Override
-    public void readFromNBT(CompoundTag compoundTag)
+    public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.readFromNBT(compoundTag);
         seat = Blocks.getBlock(compoundTag.getIntegerOrDefault("Block", Blocks.SEAT.id()));
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java
index a699744a0..5b07d71ad 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntitySensor.java
@@ -2,6 +2,7 @@ package net.minecraft.core.block.entity;
 
 import java.util.List;
 
+import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.BlockLogicMotionSensor;
@@ -13,6 +14,7 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 
 public class TileEntitySensor extends TileEntity {
 
@@ -94,6 +96,16 @@ public class TileEntitySensor extends TileEntity {
 		}
 	}
 
+	@Override
+	public void readAdditionalData(@NotNull CompoundTag compoundTag) {
+
+	}
+
+	@Override
+	public void writeAdditionalData(@NotNull CompoundTag compoundTag) {
+
+	}
+
 	@Override
 	public void heldTick(World world, Entity holder) {
 		if(world == null || carriedBlock == null || world.isClientSide) {
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 d32e914b4..67bca0761 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
@@ -7,6 +7,7 @@ import net.minecraft.core.net.command.TextFormatting;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.PacketTileEntityData;
 import net.minecraft.core.util.helper.UUIDHelper;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.UUID;
@@ -27,38 +28,36 @@ public class TileEntitySign extends TileEntity
     }
 
     @Override
-	public void writeToNBT(CompoundTag tag)
+	public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(tag);
-        tag.putString("Text1", signText[0]);
-        tag.putString("Text2", signText[1]);
-        tag.putString("Text3", signText[2]);
-        tag.putString("Text4", signText[3]);
-        tag.putInt("Picture", selectedPicture);
-        tag.putInt("Color", selectedColor);
-        tag.putBoolean("Glowing", glowing);
-        UUIDHelper.writeToTag(tag, owner, "OwnerUUID");
+        compoundTag.putString("Text1", signText[0]);
+        compoundTag.putString("Text2", signText[1]);
+        compoundTag.putString("Text3", signText[2]);
+        compoundTag.putString("Text4", signText[3]);
+        compoundTag.putInt("Picture", selectedPicture);
+        compoundTag.putInt("Color", selectedColor);
+        compoundTag.putBoolean("Glowing", glowing);
+        UUIDHelper.writeToTag(compoundTag, owner, "OwnerUUID");
     }
 
     @Override
-	public void readFromNBT(CompoundTag tag)
+    public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.readFromNBT(tag);
         for(int i = 0; i < 4; i++)
         {
-            signText[i] = tag.getString("Text" + (i + 1));
+            signText[i] = compoundTag.getString("Text" + (i + 1));
             if(signText[i].length() > MAX_LINE_SIZE)
             {
                 signText[i] = signText[i].substring(0, MAX_LINE_SIZE);
             }
         }
-        selectedPicture = tag.getIntegerOrDefault("Picture", 0);
-        selectedColor = tag.getIntegerOrDefault("Color", 15);
-        glowing = tag.getBooleanOrDefault("Glowing", false);
+        selectedPicture = compoundTag.getIntegerOrDefault("Picture", 0);
+        selectedColor = compoundTag.getIntegerOrDefault("Color", 15);
+        glowing = compoundTag.getBooleanOrDefault("Glowing", false);
 
-        UUID ownerUUID = UUIDHelper.readFromTag(tag, "OwnerUUID");
+        UUID ownerUUID = UUIDHelper.readFromTag(compoundTag, "OwnerUUID");
         if (ownerUUID == null) {
-            String s = tag.getString("Owner");
+            String s = compoundTag.getString("Owner");
             if (!s.isEmpty()) {
                 UUIDHelper.runConversionAction(s,
                     (uuid) -> this.owner = uuid,
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityStatue.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityStatue.java
index e933f3b10..086a2a629 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityStatue.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityStatue.java
@@ -51,9 +51,7 @@ public class TileEntityStatue
     private @NotNull Pose pose = Pose.DEFAULT;
 
     @Override
-    public void writeToNBT(CompoundTag tag) {
-        super.writeToNBT(tag);
-
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag) {
         // Write armor
         final @NotNull ListTag list = new ListTag();
         for (int i = 0; i < getNumArmorSlots(); i++) {
@@ -68,25 +66,23 @@ public class TileEntityStatue
                 }
             }
         }
-        tag.putList("Armor", list);
+        compoundTag.putList("Armor", list);
 
         // Write pose
-        tag.putByte("Pose", (byte) this.pose.ordinal());
+        compoundTag.putByte("Pose", (byte) this.pose.ordinal());
 
         // Write held item
         if (getHeldItem() != null) {
             final @NotNull CompoundTag heldItemTag = new CompoundTag();
             getHeldItem().writeToNBT(heldItemTag);
-            tag.putCompound("HeldItem", heldItemTag);
+            compoundTag.putCompound("HeldItem", heldItemTag);
         }
     }
 
     @Override
-    public void readFromNBT(CompoundTag tag) {
-        super.readFromNBT(tag);
-
+    public void readAdditionalData(@NotNull CompoundTag compoundTag) {
         // Read armor
-        final @Nullable ListTag list = tag.getList("Armor");
+        final @Nullable ListTag list = compoundTag.getList("Armor");
         if (list != null) {
             for (Tag<?> t : list) {
                 if (t instanceof CompoundTag) {
@@ -106,14 +102,14 @@ public class TileEntityStatue
         }
 
         // Read pose
-        byte pose = tag.getByteOrDefault("Pose", (byte) Pose.DEFAULT.ordinal());
+        byte pose = compoundTag.getByteOrDefault("Pose", (byte) Pose.DEFAULT.ordinal());
         if (pose < 0 || pose >= Pose.values().length) {
             pose = (byte) Pose.DEFAULT.ordinal();
         }
         this.pose = Pose.values()[pose];
 
         // Read held item
-        final @Nullable CompoundTag heldItemTag = tag.getCompoundOrDefault("HeldItem", null);
+        final @Nullable CompoundTag heldItemTag = compoundTag.getCompoundOrDefault("HeldItem", null);
         if (heldItemTag != null) {
             final @Nullable ItemStack heldItem = ItemStack.readItemStackFromNbt(heldItemTag);
             if (heldItem != null) {
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 d2c26dfd3..dbab2da7e 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
@@ -23,6 +23,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 
@@ -101,10 +102,9 @@ public class TileEntityTrommel extends TileEntity
     }
 
     @Override
-	public void readFromNBT(CompoundTag nbttagcompound)
+	public void readAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.readFromNBT(nbttagcompound);
-        ListTag nbttaglist = nbttagcompound.getList("Items");
+        ListTag nbttaglist = compoundTag.getList("Items");
         itemStacks = new ItemStack[getContainerSize()];
         for(int i = 0; i < nbttaglist.tagCount(); i++)
         {
@@ -116,17 +116,16 @@ public class TileEntityTrommel extends TileEntity
             }
         }
 
-        burnTime = nbttagcompound.getShort("BurnTime");
-        itemPopTime = nbttagcompound.getShort("CookTime");
+        burnTime = compoundTag.getShort("BurnTime");
+        itemPopTime = compoundTag.getShort("CookTime");
         currentItemBurnTime = getItemBurnTime(itemStacks[1]);
     }
 
     @Override
-	public void writeToNBT(CompoundTag nbttagcompound)
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(nbttagcompound);
-        nbttagcompound.putShort("BurnTime", (short) burnTime);
-        nbttagcompound.putShort("CookTime", (short) itemPopTime);
+        compoundTag.putShort("BurnTime", (short) burnTime);
+        compoundTag.putShort("CookTime", (short) itemPopTime);
         ListTag nbttaglist = new ListTag();
         for(int i = 0; i < itemStacks.length; i++)
         {
@@ -139,7 +138,7 @@ public class TileEntityTrommel extends TileEntity
             }
         }
 
-        nbttagcompound.put("Items", nbttaglist);
+        compoundTag.put("Items", nbttaglist);
     }
 
     @Override
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 1e44799d6..197dcd691 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
@@ -9,6 +9,7 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.phys.AABB;
 import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
@@ -188,38 +189,36 @@ public class TileEntityMovingPistonBlock extends TileEntity
     }
 
     @Override
-	public void readFromNBT(CompoundTag tag)
-    {
-        super.readFromNBT(tag);
-        movedId = tag.getInteger("blockId");
-        movedData = tag.getInteger("blockData");
-        if (tag.containsKey("tileEntity")) {
-            CompoundTag entityTag = tag.getCompound("tileEntity");
+    public void readAdditionalData(@NotNull CompoundTag compoundTag) {
+        movedId = compoundTag.getInteger("blockId");
+        movedData = compoundTag.getInteger("blockData");
+        if (compoundTag.containsKey("tileEntity")) {
+            CompoundTag entityTag = compoundTag.getCompound("tileEntity");
             movedEntity = TileEntityDispatcher.createAndLoadEntity(entityTag);
         }
-        direction = Direction.getDirectionById(tag.getInteger("facing"));
-        progressO = progress = tag.getFloat("progress");
-        extending = tag.getBoolean("extending");
+        direction = Direction.getDirectionById(compoundTag.getInteger("facing"));
+        progressO = progress = compoundTag.getFloat("progress");
+        extending = compoundTag.getBoolean("extending");
     }
 
     @Override
-	public void writeToNBT(CompoundTag tag)
+    public void writeAdditionalData(@NotNull CompoundTag compoundTag)
     {
-        super.writeToNBT(tag);
-        tag.putInt("blockId", movedId);
-        tag.putInt("blockData", movedData);
+        compoundTag.putInt("blockId", movedId);
+        compoundTag.putInt("blockData", movedData);
         if (movedEntity != null) {
             CompoundTag entityTag = new CompoundTag();
             movedEntity.writeToNBT(entityTag);
-            tag.put("tileEntity", entityTag);
+            compoundTag.put("tileEntity", entityTag);
         }
-        tag.putInt("facing", direction.getId());
-        tag.putFloat("progress", progressO);
-        tag.putBoolean("extending", extending);
+        compoundTag.putInt("facing", direction.getId());
+        compoundTag.putFloat("progress", progressO);
+        compoundTag.putBoolean("extending", extending);
     }
 
     @Override
     public boolean canBeCarried(World world, Entity potentialHolder) {
+        // Explicitly defined as false since the MovingPistonBlock should *never* be carried
         return false;
     }
 }
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 364b45ff6..8b8c47d2f 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
@@ -859,16 +859,6 @@ public abstract class Mob extends Entity
 
             float f3 = 0.1627714F / (movementScale * movementScale * movementScale);
             moveRelative(moveStrafing, moveForward, onGround ? speed * f3 : flySpeed);
-            movementScale = 0.91F;
-            if(onGround)
-            {
-                movementScale = 0.5460001F;
-                if(floorBlockId > 0)
-                {
-                    movementScale = Blocks.blocksList[floorBlockId].friction * 0.91F;
-                }
-
-            }
             if(canClimb())
             {
                 float f4 = 0.15F;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonsterArmored.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonsterArmored.java
index ad76c65fa..13a350c64 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonsterArmored.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonsterArmored.java
@@ -17,13 +17,20 @@ public abstract class MobMonsterArmored<T extends IArmorShape>
     extends MobMonster
     implements IArmorWearing<T>, IItemHolding {
 
-    private static final int DATA_ITEM_HELD = 24;
-    private static final int DATA_ARMOR_START = 25;
+    protected static final int DATA_ITEM_HELD = 24;
+    protected static final int DATA_ARMOR_START = 25;
+    protected static final int FLAG_LEFT_HANDED = 4;
 
     public MobMonsterArmored(final @Nullable World world) {
         super(world);
     }
 
+    @Override
+    public void spawnInit() {
+        super.spawnInit();
+        setSharedFlag(FLAG_LEFT_HANDED, this.random.nextInt(10) == 0);
+    }
+
     @Override
     public @Nullable ItemStack getItemInArmorSlot(final @NotNull T slot) {
         return this.entityData.getItemStack(DATA_ARMOR_START + slot.getSlotIndex());
@@ -46,7 +53,7 @@ public abstract class MobMonsterArmored<T extends IArmorShape>
 
     @Override
     public boolean isLeftHanded() {
-        return false;
+        return getSharedFlag(FLAG_LEFT_HANDED);
     }
 
     @Override
@@ -76,6 +83,7 @@ public abstract class MobMonsterArmored<T extends IArmorShape>
             }
         }
         tag.putList("Armor", list);
+        tag.putBoolean("LeftHanded", getSharedFlag(FLAG_LEFT_HANDED));
     }
 
     @Override
@@ -100,6 +108,7 @@ public abstract class MobMonsterArmored<T extends IArmorShape>
                 }
             }
         }
+        setSharedFlag(FLAG_LEFT_HANDED, tag.getBoolean("LeftHanded"));
     }
 
     @Override
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 8a7d9fa9f..4a1e29987 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
@@ -40,7 +40,6 @@ import net.minecraft.core.entity.vehicle.EntityMinecart;
 import net.minecraft.core.enums.ArtType;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.enums.EnumSleepStatus;
-import net.minecraft.core.item.IArmorItem;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.Items;
@@ -1563,7 +1562,7 @@ public abstract class Player
         return lastDeathCoordinate;
     }
 
-    public void pickBlock(int x, int y, int z) {
+    public void pickBlock(int x, int y, int z, boolean pickFully) {
         Block<?> block = world.getBlock(x, y, z);
     	int meta = world.getBlockMetadata(x, y, z);
     	
@@ -1578,11 +1577,17 @@ public abstract class Player
     	if(selectItem == null) {
     		return;
     	}
+
+        if (pickFully && gamemode == Gamemode.creative && tileEntity != null) {
+            CompoundTag entityTag = new CompoundTag();
+            tileEntity.writeAdditionalData(entityTag);
+            selectItem.getData().put("tileEntityData", entityTag);
+        }
     	
 		//Find item in hotbar, and select it
 		for(int i=0; i < 9; i++) {
 			ItemStack stack = inventory.getItem(i + inventory.getHotbarOffset());
-			if(stack != null && stack.itemID == selectItem.itemID && stack.getMetadata() == selectItem.getMetadata()) {
+			if(stack != null && stack.itemID == selectItem.itemID && stack.getMetadata() == selectItem.getMetadata() && stack.getData().equals(selectItem.getData())) {
 				setCurrentItem(i + inventory.getHotbarOffset());
 				return;
 			}
@@ -1604,7 +1609,7 @@ public abstract class Player
 		int stackSize = -1;
 		for(int i=9; i < 36; i++) {
 			ItemStack stack = inventory.getItem(i);
-			if(stack != null && stack.itemID == selectItem.itemID && stack.getMetadata() == selectItem.getMetadata()) {
+			if(stack != null && stack.itemID == selectItem.itemID && stack.getMetadata() == selectItem.getMetadata() && stack.getData().equals(selectItem.getData())) {
 				if(stackSize == -1 || stack.stackSize < stackSize) {
 					itemSlot = i;
 					stackSize = stack.stackSize;
@@ -1714,10 +1719,26 @@ public abstract class Player
 
     public static class PlayerConfig {
         public static final int MASK_LEFT_HAND = 0b0000_0001;
+        public static final int MASK_CAPE = 0b0000_0010;
+        public static final int MASK_OUTER_HEAD = 0b0000_0100;
+        public static final int MASK_OUTER_TORSO = 0b0000_1000;
+        public static final int MASK_OUTER_ARM_LEFT = 0b0001_0000;
+        public static final int MASK_OUTER_ARM_RIGHT = 0b0010_0000;
+        public static final int MASK_OUTER_LEG_LEFT = 0b0100_0000;
+        public static final int MASK_OUTER_LEG_RIGHT = 0b1000_0000;
 
         public PlayerConfigListener listener;
         public byte config = 0;
 
+        private void setToggle(boolean flag, int mask) {
+            if (flag) {
+                config = (byte) (config | mask);
+            } else {
+                config = (byte) (config & ~mask);
+            }
+            if (listener != null) listener.onValueChange();
+        }
+
         public void assignListener(PlayerConfigListener listener) {
             this.listener = listener;
         }
@@ -1725,15 +1746,22 @@ public abstract class Player
         public boolean isLeftHand() {
             return (config & MASK_LEFT_HAND) != 0;
         }
-
-        public void setLeftHand(boolean leftHand) {
-            if (leftHand) {
-                config |= MASK_LEFT_HAND;
-            } else {
-                config &= ~MASK_LEFT_HAND;
-            }
-            if (listener != null) listener.onValueChange();
-        }
+        public boolean capeEnabled() {return (config & MASK_CAPE) != 0;}
+        public boolean hatEnabled() {return (config & MASK_OUTER_HEAD) != 0;}
+        public boolean jacketEnabled() {return (config & MASK_OUTER_TORSO) != 0;}
+        public boolean sleeveLeftEnabled() {return (config & MASK_OUTER_ARM_LEFT) != 0;}
+        public boolean sleeveRightEnabled() {return (config & MASK_OUTER_ARM_RIGHT) != 0;}
+        public boolean pantLeftEnabled() {return (config & MASK_OUTER_LEG_LEFT) != 0;}
+        public boolean pantRightEnabled() {return (config & MASK_OUTER_LEG_RIGHT) != 0;}
+
+        public void setLeftHand(boolean leftHand) {setToggle(leftHand, MASK_LEFT_HAND);}
+        public void setCape(boolean cape) {setToggle(cape, MASK_CAPE);}
+        public void setHat(boolean hat) {setToggle(hat, MASK_OUTER_HEAD);}
+        public void setJacket(boolean jacket) {setToggle(jacket, MASK_OUTER_TORSO);}
+        public void setSleeveLeft(boolean sleeveLeft) {setToggle(sleeveLeft, MASK_OUTER_ARM_LEFT);}
+        public void setSleeveRight(boolean sleeveRight) {setToggle(sleeveRight, MASK_OUTER_ARM_RIGHT);}
+        public void setPantLeft(boolean pantLeft) {setToggle(pantLeft, MASK_OUTER_LEG_LEFT);}
+        public void setPantRight(boolean pantRight) {setToggle(pantRight, MASK_OUTER_LEG_RIGHT);}
 
         public interface PlayerConfigListener {
             void onValueChange();
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 14eac3f09..b3ad57d07 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
@@ -67,7 +67,7 @@ public class EntityBoat extends Entity
         CompoundTag flagData = this.flag.getData().getCompoundOrDefault("FlagData", null);
         if (flagData != null)
         {
-            this.tileEntityFlag.readFlagNBT(flagData);
+            this.tileEntityFlag.readAdditionalData(flagData);
         }
     }
 
@@ -238,6 +238,7 @@ public class EntityBoat extends Entity
         zo = z;
         final int waterSections = 5;
         double bouyancy = 0.0D;
+        boolean inWater = false;
         for(int i = 0; i < waterSections; i++) // Splits the boat into individual sections to measure how submerged it is, 1 being fully submerged, 0 being fully exposed
         {
             double minY = (bb.minY + ((bb.maxY - bb.minY) * (double)(i)) / (double)waterSections) - 0.125D;
@@ -246,6 +247,7 @@ public class EntityBoat extends Entity
             if(world.isAABBInMaterial(axisalignedbb, Material.water))
             {
                 bouyancy += 1.0D / (double)waterSections;
+                inWater = true;
             }
         }
 
@@ -302,7 +304,7 @@ public class EntityBoat extends Entity
 
         move(xd, yd, zd);
         double horizontalSpeed = Math.sqrt(xd * xd + zd * zd);
-        if(horizontalSpeed > 0.15D)
+        if(inWater && horizontalSpeed > 0.15D)
         {
             double d12 = Math.cos(((double) yRot * Math.PI) / 180D);
             double d15 = Math.sin(((double) yRot * Math.PI) / 180D);
diff --git a/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityMinecart.java b/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityMinecart.java
index 81d25488f..b821ac823 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityMinecart.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityMinecart.java
@@ -267,6 +267,12 @@ public class EntityMinecart extends Entity implements Container {
         if(timeSinceHit > 0) timeSinceHit--;
         if(currentDamage > 0) currentDamage--;
 
+        pushesThisTick = 0;
+        pushTime *= 0.98f;
+        if (pushTime < 0.05f || (pushTime < 0.25 && onGround)){
+            pushTime = 0;
+        }
+
         double _xo = x;
         double _yo = y;
         double _zo = z;
@@ -286,8 +292,33 @@ public class EntityMinecart extends Entity implements Container {
                 setRot(yRot, xRot);
             }
         } else {
+            yd -= 0.08D;
             motionIteration();
             motionIteration();
+
+            int blockX = MathHelper.floor(x);
+            int blockY = MathHelper.floor(y);
+            int blockZ = MathHelper.floor(z);
+            Block<?> block = world.getBlock(blockX, blockY, blockZ);
+            if (block == null || !(block.getLogic() instanceof BlockLogicRail)) {
+                double motionScale = 1;
+
+                if(onGround) {
+                    motionScale = 0.546F;
+                    if(block != null)
+                    {
+                        motionScale = block.friction * 0.91F;
+                    }
+                } else {
+                    motionScale = 0.99;
+                    motionScale = MathHelper.lerp(motionScale, 1f, pushTime);
+                }
+
+                xd *= motionScale;
+                zd *= motionScale;
+
+                move(xd, yd, zd);
+            }
         }
         this.xo = _xo;
         this.yo = _yo;
@@ -300,7 +331,6 @@ public class EntityMinecart extends Entity implements Container {
         xo = x;
         yo = y;
         zo = z;
-        yd -= 0.04D;
         int blockX = MathHelper.floor(x);
         int blockY = MathHelper.floor(y);
         int blockZ = MathHelper.floor(z);
@@ -475,21 +505,6 @@ public class EntityMinecart extends Entity implements Container {
                     }
                 }
             }
-        } else {
-            xd = MathHelper.clamp(xd, -maxSpeed, maxSpeed);
-            zd = MathHelper.clamp(zd, -maxSpeed, maxSpeed);
-
-            if(onGround) {
-                xd *= 0.5D;
-                yd *= 0.5D;
-                zd *= 0.5D;
-            }
-            move(xd, yd, zd);
-            if(!onGround) {
-                xd *= 0.95D;
-                yd *= 0.95D;
-                zd *= 0.95D;
-            }
         }
         xRot = 0.0F;
         double diffX = xo - x;
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 8983d06d8..742178d66 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
@@ -157,7 +157,7 @@ public class Item implements ITaggable<Item>, IItemConvertible
         return this;
     }
 
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
         return false;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemBed.java b/game/core/src/main/java/net/minecraft/core/item/ItemBed.java
index 3fb6abc01..ae294b121 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemBed.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemBed.java
@@ -5,6 +5,8 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class ItemBed extends Item
 {
@@ -15,14 +17,14 @@ public class ItemBed extends Item
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
     	if(!world.canPlaceInsideBlock(blockX, blockY, blockZ)) {
     		blockX += side.getOffsetX();
     		blockY += side.getOffsetY();
     		blockZ += side.getOffsetZ();
     	}
-        int i1 = entityplayer.getHorizontalPlacementDirection(null).getOpposite().getHorizontalIndex();
+        int i1 = player.getHorizontalPlacementDirection(null).getOpposite().getHorizontalIndex();
         byte byte0 = 0;
         byte byte1 = 0;
         if(i1 == 0)
@@ -43,8 +45,8 @@ public class ItemBed extends Item
         }
         if(world.isAirBlock(blockX, blockY, blockZ) && world.isAirBlock(blockX + byte0, blockY, blockZ + byte1) && world.canPlaceOnSurfaceOfBlock(blockX, blockY - 1, blockZ) && world.canPlaceOnSurfaceOfBlock(blockX + byte0, blockY - 1, blockZ + byte1))
         {
-            if(world.canBlockBePlacedAt(Blocks.BED.id(), blockX, blockY, blockZ, false, side) && itemstack.consumeItem(entityplayer)) {
-                world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.BED, EnumBlockSoundEffectType.PLACE);
+            if(world.canBlockBePlacedAt(Blocks.BED.id(), blockX, blockY, blockZ, false, side) && itemstack.consumeItem(player)) {
+                world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.BED, EnumBlockSoundEffectType.PLACE);
                 world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.BED.id(), i1);
                 world.setBlockAndMetadataWithNotify(blockX + byte0, blockY, blockZ + byte1, Blocks.BED.id(), i1 + 8);
                 return true;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemDiscMusic.java b/game/core/src/main/java/net/minecraft/core/item/ItemDiscMusic.java
index b276c13d4..c9b7e4302 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemDiscMusic.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemDiscMusic.java
@@ -7,6 +7,8 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.LevelListener;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
@@ -25,14 +27,14 @@ public class ItemDiscMusic extends Item
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
         if(world.getBlockId(blockX, blockY, blockZ) == Blocks.JUKEBOX.id() && world.getBlockMetadata(blockX, blockY, blockZ) == 0)
         {
             if (!world.isClientSide) {
                 Blocks.JUKEBOX.getLogic().playRecord(world, blockX, blockY, blockZ, id);
                 world.playBlockEvent(null, LevelListener.EVENT_JUKEBOX_TOGGLE, blockX, blockY, blockZ, id);
-                itemstack.consumeItem(entityplayer);
+                itemstack.consumeItem(player);
             }
             return true;
         } else
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemDoor.java b/game/core/src/main/java/net/minecraft/core/item/ItemDoor.java
index bba919c71..aa488e2c1 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemDoor.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemDoor.java
@@ -7,6 +7,8 @@ import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
@@ -22,7 +24,7 @@ public class ItemDoor extends Item {
     }
 
 	@Override
-	public boolean onUseItemOnBlock(ItemStack itemstack, Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+	public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
 		if(!world.canPlaceInsideBlock(blockX, blockY, blockZ)) {
 			blockX += side.getOffsetX();
 			blockY += side.getOffsetY();
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemDoorPainted.java b/game/core/src/main/java/net/minecraft/core/item/ItemDoorPainted.java
index 0b53ff9e3..645c306a7 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemDoorPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemDoorPainted.java
@@ -7,13 +7,15 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class ItemDoorPainted extends ItemDoor {
     public ItemDoorPainted(String name, String namespaceId, int id, Block<?> doorBottom, Block<?> doorTopId) {
         super(name, namespaceId, id, doorBottom, doorTopId);
     }
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
         if(!world.canPlaceInsideBlock(blockX, blockY, blockZ)) {
             blockX += side.getOffsetX();
             blockY += side.getOffsetY();
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemDye.java b/game/core/src/main/java/net/minecraft/core/item/ItemDye.java
index f28d368c0..34f810ec5 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemDye.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemDye.java
@@ -17,6 +17,7 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.biome.Biomes;
 import net.minecraft.core.world.type.WorldTypes;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
@@ -38,7 +39,7 @@ public class ItemDye extends Item
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
         if (world.getBlockId(blockX, blockY, blockZ) == Blocks.SIGN_POST_PLANKS_OAK.id() || world.getBlockId(blockX, blockY, blockZ) == Blocks.SIGN_WALL_PLANKS_OAK.id())
         {
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemFireStriker.java b/game/core/src/main/java/net/minecraft/core/item/ItemFireStriker.java
index 593c81c89..ec98da5a3 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemFireStriker.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemFireStriker.java
@@ -12,6 +12,8 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
@@ -26,7 +28,7 @@ public class ItemFireStriker extends Item
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
     	blockX += side.getOffsetX();
     	blockY += side.getOffsetY();
@@ -36,7 +38,7 @@ public class ItemFireStriker extends Item
         {
             if(world.setBlockWithNotify(blockX, blockY, blockZ, Blocks.FIRE.id())){
                 world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (double) blockX + 0.5D, (double) blockY + 0.5D, (double) blockZ + 0.5D, "fire.ignite", 1.0F, itemRand.nextFloat() * 0.4F + 0.8F);
-                itemstack.damageItem(1, entityplayer);
+                itemstack.damageItem(1, player);
                 return true;
             }
             return false;
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 7be3d76fe..db8f6d63e 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
@@ -11,6 +11,8 @@ import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class ItemFlag extends Item
 {
@@ -29,21 +31,21 @@ public class ItemFlag extends Item
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack stack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack stack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
         // copy flag data to empty flag
-		if (world.getBlockId(blockX, blockY, blockZ) == Blocks.FLAG.id() && !entityplayer.isSneaking()) {
+		if (world.getBlockId(blockX, blockY, blockZ) == Blocks.FLAG.id() && !player.isSneaking()) {
 			TileEntityFlag flag = (TileEntityFlag) world.getTileEntity(blockX, blockY, blockZ);
 			if (flag != null) {
 				CompoundTag flagData = stack.getData().getCompoundOrDefault("FlagData", new CompoundTag());
 				if (hasFlagBeenDrawnOn(stack) && doesFlagContainDyes(stack)) {
-					entityplayer.sendStatusMessage(I18n.getInstance().translateKey("flag.overwrite"));
+					player.sendStatusMessage(I18n.getInstance().translateKey("flag.overwrite"));
 					return false;
 				}
 				flag.copyFlagNBT(flagData);
-                UUIDHelper.writeToTag(flagData, entityplayer.uuid, "OwnerUUID"); // Sets the owner of the copied flag to the current player so they can actually modify the flag once they place it
+                UUIDHelper.writeToTag(flagData, player.uuid, "OwnerUUID"); // Sets the owner of the copied flag to the current player so they can actually modify the flag once they place it
 				stack.getData().putCompound("FlagData", flagData);
-				entityplayer.sendStatusMessage(I18n.getInstance().translateKey("flag.copied"));
+				player.sendStatusMessage(I18n.getInstance().translateKey("flag.copied"));
 				return true;
 			}
 		}
@@ -70,22 +72,22 @@ public class ItemFlag extends Item
             return false;
         }
 
-        world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.FLAG, EnumBlockSoundEffectType.PLACE);
+        world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.FLAG, EnumBlockSoundEffectType.PLACE);
         world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.FLAG.id(), 0);
         
-        stack.consumeItem(entityplayer);
+        stack.consumeItem(player);
         TileEntityFlag tileEntityFlag = (TileEntityFlag) world.getTileEntity(blockX, blockY, blockZ);
         if(tileEntityFlag != null)
         {
             CompoundTag flagData = stack.getData().getCompoundOrDefault("FlagData", null);
             if (flagData != null)
             {
-                tileEntityFlag.readFlagNBT(flagData);
+                tileEntityFlag.readAdditionalData(flagData);
             }
 
             if (!world.isClientSide && tileEntityFlag.owner == null)
             {
-                entityplayer.displayFlagEditorScreen(tileEntityFlag);
+                player.displayFlagEditorScreen(tileEntityFlag);
             }
         }
         return true;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemJar.java b/game/core/src/main/java/net/minecraft/core/item/ItemJar.java
index 0aaedb7b0..8ab94936b 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemJar.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemJar.java
@@ -22,7 +22,7 @@ public class ItemJar extends ItemPlaceable {
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack stack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+    public boolean onUseItemOnBlock(@NotNull ItemStack stack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
         if (player != null && player.isSneaking()) {
             return super.onUseItemOnBlock(stack, player, world, blockX, blockY, blockZ, side, xPlaced, yPlaced);
         }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemMap.java b/game/core/src/main/java/net/minecraft/core/item/ItemMap.java
index 5a78c5cc2..19df19513 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemMap.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemMap.java
@@ -14,6 +14,7 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.block.material.MaterialColor;
 import net.minecraft.core.world.saveddata.maps.ItemMapSavedData;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.HashMap;
@@ -119,7 +120,7 @@ public class ItemMap extends Item implements IComplexItem
 		return itemstack;
 	}
 	@Override
-	public boolean onUseItemOnBlock(ItemStack itemstack, Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+	public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
 		if (world.getBlockId(blockX, blockY, blockZ) == Blocks.FLAG.id()) {
 			ItemMapSavedData mapData = getOrCreateSavedData(itemstack, world);
 			if (mapData != null){
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemMinecart.java b/game/core/src/main/java/net/minecraft/core/item/ItemMinecart.java
index 48656bc64..bc9561ffd 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemMinecart.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemMinecart.java
@@ -10,6 +10,7 @@ import net.minecraft.core.entity.vehicle.EntityMinecart;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
@@ -23,7 +24,7 @@ public class ItemMinecart extends Item {
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
         Block<?> block = world.getBlock(blockX, blockY, blockZ);
         if (!Block.hasLogicClass(block, BlockLogicRail.class)) { return false; }
 
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 8f57e967f..a6569b680 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
@@ -12,6 +12,7 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
@@ -26,7 +27,7 @@ public class ItemPaintBrush extends Item {
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
         if (itemstack.getMetadata() >= itemstack.getMaxDamage()) {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemPainting.java b/game/core/src/main/java/net/minecraft/core/item/ItemPainting.java
index 48b3051b8..00fb3dfd2 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemPainting.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemPainting.java
@@ -6,6 +6,8 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class ItemPainting extends Item
 {
@@ -27,7 +29,7 @@ public class ItemPainting extends Item
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
     	int sideHit = side.getId();
         if(sideHit == 0)
@@ -51,15 +53,15 @@ public class ItemPainting extends Item
         {
             direction = 3;
         }
-        EntityPainting entity = new EntityPainting(world, blockX, blockY, blockZ, direction, entityplayer.getSelectedArt().key);
+        EntityPainting entity = new EntityPainting(world, blockX, blockY, blockZ, direction, player.getSelectedArt().key);
         if(entity.canStay())
         {
             if(!world.isClientSide)
             {
                 world.entityJoinedWorld(entity);
             }
-            world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.PLANKS_OAK, EnumBlockSoundEffectType.PLACE);
-            itemstack.consumeItem(entityplayer);
+            world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.PLANKS_OAK, EnumBlockSoundEffectType.PLACE);
+            itemstack.consumeItem(player);
             return true;
         }
         return false;
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemPebble.java b/game/core/src/main/java/net/minecraft/core/item/ItemPebble.java
index 0ada25eff..53dc3bb0e 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemPebble.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemPebble.java
@@ -10,6 +10,8 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
@@ -37,7 +39,7 @@ public class ItemPebble extends Item implements IDispensable
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
         int id = world.getBlockId(blockX, blockY, blockZ);
         int meta = world.getBlockMetadata(blockX, blockY, blockZ);
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemPlaceable.java b/game/core/src/main/java/net/minecraft/core/item/ItemPlaceable.java
index 2f08bbaa2..b8bb07a6b 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemPlaceable.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemPlaceable.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.item;
 
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.player.Player;
@@ -8,6 +9,7 @@ import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
@@ -23,7 +25,7 @@ public class ItemPlaceable extends Item {
 	}
 
 	@Override
-	public boolean onUseItemOnBlock(ItemStack stack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+	public boolean onUseItemOnBlock(@NotNull ItemStack stack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
 		if(stack.stackSize <= 0) {
 			return false;
 		}
@@ -43,6 +45,12 @@ public class ItemPlaceable extends Item {
 				} else {
 					blockToPlace.onBlockPlacedByMob(world, blockX, blockY, blockZ, side, player, xPlaced, yPlaced);
 				}
+				if (blockToPlace.isEntityTile && stack.getData().containsKey("tileEntityData")) {
+					TileEntity tileEntity = world.getTileEntity(blockX, blockY, blockZ);
+					if (tileEntity != null) {
+						tileEntity.readAdditionalData(stack.getData().getCompound("tileEntityData"));
+					}
+				}
 				world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, blockToPlace, EnumBlockSoundEffectType.PLACE);
 				return true;
 			}
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemRope.java b/game/core/src/main/java/net/minecraft/core/item/ItemRope.java
index bf6d2d424..168211d5d 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemRope.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemRope.java
@@ -6,6 +6,7 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class ItemRope extends ItemPlaceable {
@@ -13,7 +14,7 @@ public class ItemRope extends ItemPlaceable {
         super(name, namespaceId, id, blockToPlace);
     }
     @Override
-    public boolean onUseItemOnBlock(ItemStack stack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+    public boolean onUseItemOnBlock(@NotNull ItemStack stack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
         if(stack.stackSize <= 0) {
             return false;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemSeeds.java b/game/core/src/main/java/net/minecraft/core/item/ItemSeeds.java
index 2d85a85ca..944f96407 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemSeeds.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemSeeds.java
@@ -10,6 +10,8 @@ import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
@@ -22,7 +24,7 @@ public class ItemSeeds extends Item {
 	}
 
 	@Override
-	public boolean onUseItemOnBlock(ItemStack itemstack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+	public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
 		if(!world.canPlaceInsideBlock(blockX, blockY, blockZ)) {
 			blockX += side.getOffsetX();
 			blockY += side.getOffsetY();
@@ -30,8 +32,8 @@ public class ItemSeeds extends Item {
 		}
 		if(world.getBlockId(blockX, blockY - 1, blockZ) == Blocks.FARMLAND_DIRT.id() && world.canPlaceInsideBlock(blockX, blockY, blockZ)) {
 			if(world.setBlockWithNotify(blockX, blockY, blockZ, cropsBlock.id())) {
-				world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, cropsBlock, EnumBlockSoundEffectType.PLACE);
-				itemstack.consumeItem(entityplayer);
+				world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, cropsBlock, EnumBlockSoundEffectType.PLACE);
+				itemstack.consumeItem(player);
 				return true;
 			}
 		}
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemSign.java b/game/core/src/main/java/net/minecraft/core/item/ItemSign.java
index d8b017b82..027ca73f6 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemSign.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemSign.java
@@ -8,6 +8,8 @@ import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class ItemSign extends Item
 {
@@ -18,7 +20,7 @@ public class ItemSign extends Item
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player entityplayer, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
     	int sideHit = side.getId();
         if(side == Side.BOTTOM)
@@ -44,19 +46,19 @@ public class ItemSign extends Item
         }
         if(sideHit == 1)
         {
-            world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.SIGN_POST_PLANKS_OAK, EnumBlockSoundEffectType.PLACE);
-            world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.SIGN_POST_PLANKS_OAK.id(), MathHelper.floor((double)(((entityplayer.yRot + 180F) * 16F) / 360F) + 0.5D) & 0xf);
+            world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.SIGN_POST_PLANKS_OAK, EnumBlockSoundEffectType.PLACE);
+            world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.SIGN_POST_PLANKS_OAK.id(), MathHelper.floor((double)(((player.yRot + 180F) * 16F) / 360F) + 0.5D) & 0xf);
         } else
         {
-            world.playBlockSoundEffect(entityplayer, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.SIGN_WALL_PLANKS_OAK, EnumBlockSoundEffectType.PLACE);
+            world.playBlockSoundEffect(player, blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, Blocks.SIGN_WALL_PLANKS_OAK, EnumBlockSoundEffectType.PLACE);
             world.setBlockAndMetadataWithNotify(blockX, blockY, blockZ, Blocks.SIGN_WALL_PLANKS_OAK.id(), sideHit);
         }
-        itemstack.consumeItem(entityplayer);
+        itemstack.consumeItem(player);
         TileEntitySign tileentitysign = (TileEntitySign)world.getTileEntity(blockX, blockY, blockZ);
         if(tileentitysign != null)
         {
-            tileentitysign.setOwner(entityplayer);
-            entityplayer.displaySignEditorScreen(tileentitysign);
+            tileentitysign.setOwner(player);
+            player.displaySignEditorScreen(tileentitysign);
         }
         return true;
     }
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 dadbb39dc..08d16fb48 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
@@ -201,6 +201,7 @@ public final class ItemStack {
 		
 		if(Item.itemsList[itemID] == null) {
 			itemID = 0;
+            stackSize = 0;
 		}
 		
 		if(itemID == Blocks.CHEST_LEGACY.id()) itemID = Blocks.CHEST_PLANKS_OAK.id();
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemStatue.java b/game/core/src/main/java/net/minecraft/core/item/ItemStatue.java
index 67d5b3213..d00fa1a52 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemStatue.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemStatue.java
@@ -8,6 +8,8 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
@@ -23,7 +25,7 @@ public class ItemStatue extends Item {
     }
 
 	@Override
-	public boolean onUseItemOnBlock(ItemStack itemstack, Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
+	public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced) {
 		if(!world.canPlaceInsideBlock(blockX, blockY, blockZ)) {
 			blockX += side.getOffsetX();
 			blockY += side.getOffsetY();
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java
index 081a74f21..fc93574fe 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java
@@ -2,6 +2,7 @@ package net.minecraft.core.item.block;
 
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.player.Player;
@@ -35,7 +36,7 @@ public class ItemBlock<T extends BlockLogic> extends Item
     }
 
     @Override
-	public boolean onUseItemOnBlock(ItemStack stack, @Nullable Player player, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
+	public boolean onUseItemOnBlock(@NotNull ItemStack stack, @Nullable Player player, @NotNull World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
 		if(stack.stackSize <= 0) {
 			return false;
 		}
@@ -54,6 +55,12 @@ public class ItemBlock<T extends BlockLogic> extends Item
                     block.onBlockPlacedOnSide(world, x, y, z, side, xPlaced, yPlaced);
                 } else {
                     block.onBlockPlacedByMob(world, x, y, z, side, player, xPlaced, yPlaced);
+                }
+                if (block.isEntityTile && stack.getData().containsKey("tileEntityData")) {
+                    TileEntity tileEntity = world.getTileEntity(x, y, z);
+                    if (tileEntity != null) {
+                        tileEntity.readAdditionalData(stack.getData().getCompound("tileEntityData"));
+                    }
                 }
 				world.playBlockSoundEffect(player, x + 0.5F, y + 0.5F, z + 0.5F, block, EnumBlockSoundEffectType.PLACE);
 				return true;
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 4c855eb14..7dd11f4ab 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
@@ -12,6 +12,7 @@ import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.HitResult;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
@@ -27,7 +28,7 @@ public class ItemBlockAlgae<T extends BlockLogic> extends ItemBlock<T>
     }
     
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
     	return false;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java
index d874c0e49..065282012 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java
@@ -7,6 +7,7 @@ import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class ItemBlockLadder<T extends BlockLogicLadder> extends ItemBlock<T> {
@@ -16,7 +17,7 @@ public class ItemBlockLadder<T extends BlockLogicLadder> extends ItemBlock<T> {
 	}
 	
 	@Override
-	public boolean onUseItemOnBlock(ItemStack stack, @Nullable Player player, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
+	public boolean onUseItemOnBlock(@NotNull ItemStack stack, @Nullable Player player, @NotNull World world, int x, int y, int z, @NotNull Side side, double xPlaced, double yPlaced) {
 		Block<?> clickedBlock = world.getBlock(x, y, z);
 
 		BlockLogicLadder ladder = block.getLogic();
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayer.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayer.java
index 4f512a8a9..496956ef2 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayer.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayer.java
@@ -9,6 +9,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 
@@ -20,7 +21,7 @@ public class ItemBlockLayer<T extends BlockLogicLayerBase> extends ItemBlock<T>
 	}
 
 	@Override
-	public boolean onUseItemOnBlock(final ItemStack itemstack, final @Nullable Player player, final World world, int blockX, int blockY, int blockZ, final Side side, double xPlaced, final double yPlaced)
+	public boolean onUseItemOnBlock(final @NotNull ItemStack itemstack, final @Nullable Player player, final @NotNull World world, int blockX, int blockY, int blockZ, final @NotNull Side side, double xPlaced, final double yPlaced)
 	{
 		Block<?> targetBlock = world.getBlock(blockX, blockY, blockZ);
 		int meta = world.getBlockMetadata(blockX, blockY, blockZ);
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayerLeaves.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayerLeaves.java
index 2515d87a0..2763ce2d4 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayerLeaves.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLayerLeaves.java
@@ -11,6 +11,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class ItemBlockLayerLeaves<T extends BlockLogicLayerLeaves> extends ItemBlock<T>
@@ -21,7 +22,7 @@ public class ItemBlockLayerLeaves<T extends BlockLogicLayerLeaves> extends ItemB
 	}
 
 	@Override
-	public boolean onUseItemOnBlock(final ItemStack itemstack, final Player player, final World world, int blockX, int blockY, int blockZ, final Side side, double xPlaced, final double yPlaced)
+	public boolean onUseItemOnBlock(final @NotNull ItemStack itemstack, final @Nullable Player player, final @NotNull World world, int blockX, int blockY, int blockZ, final @NotNull Side side, double xPlaced, final double yPlaced)
 	{
 		Block<?> targetBlock = world.getBlock(blockX, blockY, blockZ);
 		int meta = world.getBlockMetadata(blockX, blockY, blockZ);
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java
index f7cfc2be5..eb7b965d0 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java
@@ -10,6 +10,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class ItemBlockSlab<T extends BlockLogic> extends ItemBlock<T>
@@ -21,7 +22,7 @@ public class ItemBlockSlab<T extends BlockLogic> extends ItemBlock<T>
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
     	int id = world.getBlockId(blockX, blockY, blockZ);
     	int meta = world.getBlockMetadata(blockX, blockY, blockZ) & 0x3;
diff --git a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolHoe.java b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolHoe.java
index ac0240994..de1239de8 100644
--- a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolHoe.java
+++ b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolHoe.java
@@ -14,6 +14,7 @@ import net.minecraft.core.item.material.ToolMaterial;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
@@ -34,7 +35,7 @@ public class ItemToolHoe extends ItemTool
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
         return till(itemstack, player, world, blockX, blockY, blockZ, side);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShovel.java b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShovel.java
index 37de18a58..192dccf15 100644
--- a/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShovel.java
+++ b/game/core/src/main/java/net/minecraft/core/item/tool/ItemToolShovel.java
@@ -12,6 +12,7 @@ import net.minecraft.core.item.material.ToolMaterial;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
@@ -30,7 +31,7 @@ public class ItemToolShovel extends ItemTool
     }
 
     @Override
-    public boolean onUseItemOnBlock(ItemStack itemstack, Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced)
+    public boolean onUseItemOnBlock(@NotNull ItemStack itemstack, @Nullable Player player, @NotNull World world, int blockX, int blockY, int blockZ, @NotNull Side side, double xPlaced, double yPlaced)
     {
         return shovelBlock(itemstack, player, world, blockX, blockY, blockZ, side);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandSpawnParticle.java b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandParticle.java
similarity index 98%
rename from game/core/src/main/java/net/minecraft/core/net/command/commands/CommandSpawnParticle.java
rename to game/core/src/main/java/net/minecraft/core/net/command/commands/CommandParticle.java
index 49f5ca96a..b16f9178b 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandSpawnParticle.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandParticle.java
@@ -19,11 +19,11 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 
-public class CommandSpawnParticle implements CommandManager.CommandRegistry {
+public class CommandParticle implements CommandManager.CommandRegistry {
     public void register(CommandDispatcher<CommandSource> dispatcher) {
         dispatcher.register
             (
-                LiteralArgumentBuilder.<CommandSource>literal("spawnparticle")
+                LiteralArgumentBuilder.<CommandSource>literal("particle")
                     .requires(CommandSource::hasAdmin)
                     .then(RequiredArgumentBuilder.<CommandSource, String>argument("particleId", ArgumentTypeParticleId.particleId())
                         .executes(c -> {
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketPlayerAction.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketPlayerAction.java
index 2a04fb891..688187e45 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketPlayerAction.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketPlayerAction.java
@@ -16,6 +16,7 @@ public class PacketPlayerAction extends Packet
     public static final int ACTION_DROP_ITEM_SINGLE = 4;
     public static final int ACTION_DROP_ITEM_STACK = 5;
     public static final int ACTION_PICK_BLOCK = 6;
+    public static final int ACTION_PICK_BLOCK_FULLY = 7;
 
     public int xPosition;
     public int yPosition;
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 ce0350e51..926eeecc7 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
@@ -54,9 +54,11 @@ public class ChunkLoaderRegion
         if(!chunk.isAtLocation(x, z))
         {
             LOGGER.warn("Chunk file at {},{} is in the wrong location; relocating. (Expected {}, {}, got {}, {})", x, z, x, z, chunk.xPosition, chunk.zPosition);
-            tag.putInt("xPos", x);
-            tag.putInt("zPos", z);
-            chunk = ChunkLoaderLegacy.loadChunkIntoWorldFromCompound(world, tag.getCompound("Level"));
+            final CompoundTag level = tag.getCompound("Level");
+            level.putInt("xPos", x);
+            level.putInt("zPos", z);
+            chunk = ChunkLoaderLegacy.loadChunkIntoWorldFromCompound(world, level);
+            assert chunk.isAtLocation(x, z);
         }
         chunk.fixMissingBlocks();
         return chunk;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureCherryTreeFancy.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureCherryTreeFancy.java
new file mode 100644
index 000000000..12d6be534
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/tree/WorldFeatureCherryTreeFancy.java
@@ -0,0 +1,428 @@
+package net.minecraft.core.world.generate.feature.tree;
+
+import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.tag.BlockTags;
+import net.minecraft.core.util.helper.MathHelper;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.generate.feature.MethodParametersAnnotation;
+import net.minecraft.core.world.generate.feature.WorldFeature;
+
+import java.util.Random;
+
+public class WorldFeatureCherryTreeFancy extends WorldFeature {
+    protected int leavesID;
+    protected int logID;
+
+    static final byte[] axisConversionArray = { 2, 0, 0, 1, 2, 1 };
+    Random rnd;
+    World world;
+    int[] origin = { 0, 0, 0 };
+    int height;
+    int trunkHeight;
+    double trunkHeightScale;
+    double branchDensity;
+    double branchSlope;
+    double widthScale;
+    double foliageDensity;
+    int trunkWidth;
+    int heightVariance;
+    int foliageHeight;
+    int[][] foliageCoords;
+    int heightMod;
+
+    @MethodParametersAnnotation(names = {"leavesID", "logID"})
+    public WorldFeatureCherryTreeFancy(int leavesID, int logID)
+    {
+        this(leavesID, logID, 0);
+    }
+
+    @MethodParametersAnnotation(names = {"leavesID", "logID", "heightMod"})
+    public WorldFeatureCherryTreeFancy(int leavesID, int logID, int heightMod)
+    {
+        rnd = new Random();
+        height = 0;
+        trunkHeightScale = 0.6D;
+        branchDensity = 1.0D;
+        branchSlope = 0.4D;
+        widthScale = 1.0D;
+        foliageDensity = 1.0D;
+        trunkWidth = 1;
+        heightVariance = 12;
+        foliageHeight = 4;
+        this.leavesID = leavesID;
+        this.logID = logID;
+        this.heightMod = heightMod;
+    }
+
+    void prepare()
+    {
+        trunkHeight = (int)((double) height * trunkHeightScale);
+        if (trunkHeight >= height)
+        {
+            trunkHeight = height - 1;
+        }
+        int numOfClustersPerY = (int)(1.4D + Math.pow((foliageDensity * (double) height) / 13D, 2D));
+        if (numOfClustersPerY < 1)
+        {
+            numOfClustersPerY = 1;
+        }
+        int[][] foliageCoords = new int[numOfClustersPerY * height][4];
+        int yEnd = (origin[1] + height) - foliageHeight;
+        int foliageCoordsIndex = 1;
+        int topY = origin[1] + trunkHeight;
+        int y = yEnd - origin[1];
+        foliageCoords[0][0] = origin[0];
+        foliageCoords[0][1] = yEnd;
+        foliageCoords[0][2] = origin[2];
+        foliageCoords[0][3] = topY;
+        yEnd--;
+        while (y >= 0) {
+            float shapeFac = shapeFunc(y);
+            if (shapeFac < 0.0F) {
+                yEnd--;
+                y--;
+            } else {
+                double offset = 0.5D;
+                for (int i = 0; i < numOfClustersPerY; i++) {
+                    double r = widthScale * ((double)shapeFac * ((double) rnd.nextFloat() + 0.328D));
+                    double theta = (double) rnd.nextFloat() * 2D * Math.PI;
+                    int x = MathHelper.floor(r * Math.sin(theta) + (double) origin[0] + offset);
+                    int z = MathHelper.floor(r * Math.cos(theta) + (double) origin[2] + offset);
+                    int[] branchEnd = { x, yEnd, z };
+                    int[] branchTopOfTree = { x, yEnd + foliageHeight, z };
+                    if (distToMat(branchEnd, branchTopOfTree) != -1) {
+                        continue;
+                    }
+                    int[] branchStart = { origin[0], origin[1], origin[2] };
+                    double dist = Math.sqrt(Math.pow(Math.abs(origin[0] - branchEnd[0]), 2D) + Math.pow(Math.abs(origin[2] - branchEnd[2]), 2D));
+                    if ((double)branchEnd[1] - dist * branchSlope > (double)topY) {
+                        branchStart[1] = topY;
+                    }
+                    else {
+                        branchStart[1] = (int)((double)branchEnd[1] - dist * branchSlope);
+                    }
+                    if(distToMat(branchStart, branchEnd) == -1) {
+                        foliageCoords[foliageCoordsIndex][0] = x;
+                        foliageCoords[foliageCoordsIndex][1] = yEnd;
+                        foliageCoords[foliageCoordsIndex][2] = z;
+                        foliageCoords[foliageCoordsIndex][3] = branchStart[1];
+                        foliageCoordsIndex++;
+                    }
+                }
+
+                yEnd--;
+                y--;
+            }
+        }
+        this.foliageCoords = new int[foliageCoordsIndex][4];
+        System.arraycopy(foliageCoords, 0, this.foliageCoords, 0, foliageCoordsIndex);
+    }
+
+    void crossSection(int x, int y, int z, float radius, int blockId, Random random)
+    {
+        int rad = (int)(radius + 0.618D);
+
+        int[] center = { x, y, z };
+        int[] coord = { 0, 0, 0 };
+
+        coord[1] = center[1];
+        for(int off1 = -rad; off1 <= rad; off1++)
+        {
+            coord[0] = center[0] + off1;
+
+            for(int off2 = -rad; off2 <= rad; off2++)
+            {
+                coord[2] = center[2] + off2;
+
+                double thisDist = Math.sqrt(Math.pow((double) Math.abs(off1) + 0.5D, 2D) + Math.pow((double) Math.abs(off2) + 0.5D, 2D));
+                if(thisDist <= (double)radius)
+                {
+                    int id = world.getBlockId(coord[0], coord[1], coord[2]);
+                    if (id == 0 || id == leavesID || id == Blocks.LEAVES_CHERRY_FLOWERING.id())
+                    {
+                        world.setBlockWithNotify(coord[0], coord[1], coord[2], random.nextInt(5) == 0 ? Blocks.LEAVES_CHERRY_FLOWERING.id() : blockId);
+                    }
+                }
+            }
+        }
+    }
+
+    float shapeFunc(int y)
+    {
+        if (y < height * 0.3D)
+        {
+            return -1.618F;
+        }
+        float radius = height / 2.0F;
+        float adj = height / 2.0F - y;
+        float dist;
+        if (adj == 0.0F) {
+            dist = radius;
+        } else if (java.lang.Math.abs(adj) >= radius) {
+            dist = 0.0F;
+        } else {
+            dist = (float) Math.sqrt(Math.pow(Math.abs(radius), 2D) - Math.pow(Math.abs(adj), 2D));
+        }
+        dist *= 0.5F;
+        return dist;
+    }
+
+    float getFoliageShape(int y)
+    {
+        if(y < 0 || y >= foliageHeight)
+        {
+            return -1F;
+        }
+        else if (y == 0 || y == foliageHeight - 1)
+        {
+            return 2F;
+        }
+        else
+        {
+            return 3F;
+        }
+    }
+
+    void foliageCluster(int x, int y, int z, Random random)
+    {
+        for(int leavesY = y; leavesY < y + foliageHeight; leavesY++)
+        {
+            float radius = getFoliageShape(leavesY - y);
+            crossSection(x, leavesY, z, radius, leavesID, random);
+        }
+    }
+
+    void makeFoliage(Random random)
+    {
+        for (int[] foliageCoord : foliageCoords)
+        {
+            int x = foliageCoord[0];
+            int y = foliageCoord[1];
+            int z = foliageCoord[2];
+            foliageCluster(x, y, z, random);
+        }
+    }
+
+    void makeBranch(int[] startPos, int[] endPos, int blockId)
+    {
+        int[] dimensions = { 0, 0, 0 };
+        int dim0 = 0;
+
+        // Find widest dimension and assign it to dim0
+        for(int i = 0; i < 3; i++)
+        {
+            dimensions[i] = endPos[i] - startPos[i];
+            if(Math.abs(dimensions[i]) > Math.abs(dimensions[dim0]))
+            {
+                dim0 = i;
+            }
+        }
+
+        if(dimensions[dim0] == 0)
+        {
+            return;
+        }
+
+        // Look up other two dimensions
+        byte dim1 = axisConversionArray[dim0];
+        byte dim2 = axisConversionArray[dim0 + 3];
+
+        byte delta;
+        if(dimensions[dim0] > 0)
+        {
+            delta = 1;
+        }
+        else
+        {
+            delta = -1;
+        }
+
+        // Determine delta scale for other two dimensions
+        double dim1DeltaScale = (double)dimensions[dim1] / (double)dimensions[dim0];
+        double dim2DeltaScale = (double)dimensions[dim2] / (double)dimensions[dim0];
+
+        // Draw line from startPos to endPos
+        for(int i = 0; i != dimensions[dim0] + delta; i += delta)
+        {
+            int[] pos = { 0, 0, 0 };
+            pos[dim0] = MathHelper.floor((double)startPos[dim0] + (double)i + 0.5D);
+            pos[dim1] = MathHelper.floor((double)startPos[dim1] + (double)i * dim1DeltaScale + 0.5D);
+            pos[dim2] = MathHelper.floor((double)startPos[dim2] + (double)i * dim2DeltaScale + 0.5D);
+            world.setBlockWithNotify(pos[0], pos[1], pos[2], blockId);
+        }
+    }
+
+    boolean isHighEnoughToBranch(int i)
+    {
+        return (double)i >= (double) height * 0.2D;
+    }
+
+    void makeTrunk()
+    {
+        int x = origin[0];
+        int minY = origin[1];
+        int maxY = origin[1] + trunkHeight;
+        int z = origin[2];
+        int[] startPos = { x, minY, z };
+        int[] endPos = { x, maxY, z };
+        makeBranch(startPos, endPos, logID);
+        if(trunkWidth == 2)
+        {
+            startPos[0]++;
+            endPos[0]++;
+            makeBranch(startPos, endPos, logID);
+            startPos[2]++;
+            endPos[2]++;
+            makeBranch(startPos, endPos, logID);
+            startPos[0]--;
+            endPos[0]--;
+            makeBranch(startPos, endPos, logID);
+        }
+    }
+
+    void makeBranches()
+    {
+        int[] startPos = { origin[0], origin[1], origin[2] };
+        for (int[] branchPoint : foliageCoords)
+        {
+            int[] endPos = { branchPoint[0], branchPoint[1], branchPoint[2] };
+            startPos[1] = branchPoint[3];
+            int dy = startPos[1] - origin[1];
+            if (isHighEnoughToBranch(dy))
+            {
+                makeBranch(startPos, endPos, logID);
+            }
+        }
+    }
+
+    int distToMat(int[] startPos, int[] endPos)
+    {
+        int[] dimensions = { 0, 0, 0 };
+        int dim0 = 0;
+
+        // Find widest dimension and assign it to dim0
+        for(byte i = 0; i < 3; i++)
+        {
+            dimensions[i] = endPos[i] - startPos[i];
+            if(Math.abs(dimensions[i]) > Math.abs(dimensions[dim0]))
+            {
+                dim0 = i;
+            }
+        }
+
+        if(dimensions[dim0] == 0)
+        {
+            return -1;
+        }
+
+        // Look up other two dimensions
+        byte dim1 = axisConversionArray[dim0];
+        byte dim2 = axisConversionArray[dim0 + 3];
+
+        byte delta;
+        if(dimensions[dim0] > 0)
+        {
+            delta = 1;
+        }
+        else
+        {
+            delta = -1;
+        }
+
+        // Determine delta scale for other two dimensions
+        double dim1DeltaScale = (double)dimensions[dim1] / (double)dimensions[dim0];
+        double dim2DeltaScale = (double)dimensions[dim2] / (double)dimensions[dim0];
+
+        // Check all blocks from startPos to endPos, breaking if interrupted
+        int linePos = 0;
+        int lineLength = dimensions[dim0] + delta;
+        while (linePos != lineLength)
+        {
+            int[] pos = { 0, 0, 0 };
+            pos[dim0] = startPos[dim0] + linePos;
+            pos[dim1] = MathHelper.floor((double)startPos[dim1] + (double)linePos * dim1DeltaScale);
+            pos[dim2] = MathHelper.floor((double)startPos[dim2] + (double)linePos * dim2DeltaScale);
+            int idAtPos = world.getBlockId(pos[0], pos[1], pos[2]);
+            if(idAtPos != 0 && idAtPos != leavesID && idAtPos != Blocks.LEAVES_CHERRY_FLOWERING.id())
+            {
+                break;
+            }
+            linePos += delta;
+        }
+
+        // Check if was interrupted; if so, return the distance we travelled, otherwise return -1
+        if(linePos == lineLength)
+        {
+            return -1;
+        }
+        else
+        {
+            return Math.abs(linePos);
+        }
+    }
+
+    boolean canGenerateTree()
+    {
+        int[] bottomPos = { origin[0], origin[1], origin[2] };
+        int[] topPos = { origin[0], (origin[1] + height) - 1, origin[2] };
+        int blockIdUnderneath = world.getBlockId(origin[0], origin[1] - 1, origin[2]);
+        if(!Blocks.hasTag(blockIdUnderneath, BlockTags.GROWS_TREES))
+        {
+            return false;
+        }
+        int interruptedTrunkHeight = distToMat(bottomPos, topPos);
+        if(interruptedTrunkHeight == -1)
+        {
+            return true;
+        }
+        if(interruptedTrunkHeight < 6)
+        {
+            return false;
+        }
+        else
+        {
+            height = interruptedTrunkHeight;
+            return true;
+        }
+    }
+
+    @Override
+    public void init(double d, double d1, double d2)
+    {
+        heightVariance = (int)(d * (12D + heightMod));
+        if(d > 0.5D)
+        {
+            foliageHeight = 5;
+        }
+        widthScale = d1;
+        foliageDensity = d2;
+    }
+
+    @Override
+    public boolean place(World world, Random random, int x, int y, int z)
+    {
+        this.world = world;
+        long seed = random.nextLong();
+        rnd.setSeed(seed);
+        origin[0] = x;
+        origin[1] = y;
+        origin[2] = z;
+        if(height == 0)
+        {
+            height = 5 + rnd.nextInt(heightVariance);
+        }
+        if(canGenerateTree())
+        {
+            WorldFeatureTree.onTreeGrown(this.world, origin[0], origin[1], origin[2]);
+            prepare();
+            makeFoliage(random);
+            makeTrunk();
+            makeBranches();
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+}
diff --git a/game/core/src/main/resources/lang/en_US/gui.lang b/game/core/src/main/resources/lang/en_US/gui.lang
index 74cfb7f12..86f765de1 100644
--- a/game/core/src/main/resources/lang/en_US/gui.lang
+++ b/game/core/src/main/resources/lang/en_US/gui.lang
@@ -189,10 +189,16 @@ gui.options.page.general.category.gameplay=Gameplay
 gui.options.page.general.category.user_interface=User Interface
 gui.options.page.general.category.miscellaneous=Miscellaneous
 
+gui.options.page.player.title=Player
+gui.options.page.player.category.player=Player
+
 gui.options.page.audio.title=Audio
 gui.options.page.audio.category.audio=Audio
 gui.options.page.audio.category.debug=Debug
 
+gui.options.page.accessibility.title=Accessibility
+gui.options.page.accessibility.category.accessibility=Accessibility
+
 gui.options.page.video.title=Video
 gui.options.page.video.category.graphics=Graphics
 gui.options.page.video.category.performance=Performance
diff --git a/game/core/src/main/resources/lang/en_US/options.lang b/game/core/src/main/resources/lang/en_US/options.lang
index 3d4a4d255..228964dca 100644
--- a/game/core/src/main/resources/lang/en_US/options.lang
+++ b/game/core/src/main/resources/lang/en_US/options.lang
@@ -174,6 +174,10 @@ options.developerMode=Developer Mode
 options.forceOnscreenKeyboard=Force On Screen Keyboard
 options.enableHolidayTextures=Enable Holiday Textures
 options.dynamicCursor=Dynamic Cursor
+options.enableDevResourceLoading=Developer Resource Loading
+
+options.fov.modification=Contextual FOV Modification
+options.screen.motion.effects=Screen Motion Effects
 
 options.tooltipStyle.default=Default
 options.tooltipStyle.modern=Modern
@@ -192,7 +196,14 @@ options.tooltipStyle.redstone_goggles=Redstone Goggles
 options.tooltipStyle.creep-o-vision=Creep-o-Vision
 options.tooltipStyle.steve=Steve
 
-options.playerLeftHanded=Left Handed
+options.player.left.handed=Left Handed
+options.player.cape=Cape
+options.player.hat=Hat
+options.player.jacket=Jacket
+options.player.sleeve.left=Left Sleeve
+options.player.sleeve.right=Right Sleeve
+options.player.pant.left=Left Pant Leg
+options.player.pant.right=Right Pant Leg
 
 key.attack=Attack
 key.interact=Interact
@@ -261,4 +272,5 @@ key.debug.iteminfo=Show extra item info
 key.debug.reloadchunks=Reload chunks
 key.debug.smoothlighting=Toggle smooth lighting
 key.debug.releasecursor=Release Cursor
-key.debug.shortcuts=Show keyboard shortcuts
\ No newline at end of file
+key.debug.shortcuts=Show keyboard shortcuts
+key.debug.loadChunksQuickly=Load Chunks Quickly
\ No newline at end of file
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 0a37607a5..9e6ac56f8 100644
--- a/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -43,7 +43,7 @@ import net.minecraft.core.net.command.commands.CommandSeed;
 import net.minecraft.core.net.command.commands.CommandSetBlock;
 import net.minecraft.core.net.command.commands.CommandSetSpawn;
 import net.minecraft.core.net.command.commands.CommandSpawn;
-import net.minecraft.core.net.command.commands.CommandSpawnParticle;
+import net.minecraft.core.net.command.commands.CommandParticle;
 import net.minecraft.core.net.command.commands.CommandSummon;
 import net.minecraft.core.net.command.commands.CommandTeleport;
 import net.minecraft.core.net.command.commands.CommandTellRaw;
@@ -418,7 +418,7 @@ public class MinecraftServer
         CommandManager.registerCommand(new CommandHeal());
         CommandManager.registerCommand(new CommandMobSpawning());
         CommandManager.registerCommand(new CommandPlaySound());
-        CommandManager.registerCommand(new CommandSpawnParticle());
+        CommandManager.registerCommand(new CommandParticle());
 
         CommandManager.registerServerCommand(new CommandStop());
         CommandManager.registerServerCommand(new CommandOp());
diff --git a/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java b/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java
index a0a111915..f65d39a62 100644
--- a/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java
+++ b/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java
@@ -113,9 +113,11 @@ public class PacketHandlerServer extends PacketHandler
 
     @Override
     public void handlePlayerConfig(PacketPlayerConfig packetPlayerConfig) {
-        playerEntity.playerConfig.config = packetPlayerConfig.config;
-        packetPlayerConfig.entityId = playerEntity.id;
-        mcServer.playerList.sendPacketToAllPlayersInDimension(packetPlayerConfig, playerEntity.dimension);
+        if (playerEntity.playerConfig.config != packetPlayerConfig.config) {
+            playerEntity.playerConfig.config = packetPlayerConfig.config;
+            packetPlayerConfig.entityId = playerEntity.id;
+            mcServer.playerList.sendPacketToAllPlayersInDimension(packetPlayerConfig, playerEntity.dimension);
+        }
     }
 
     @Override
@@ -319,18 +321,23 @@ public class PacketHandlerServer extends PacketHandler
 
         if (!canInteract() || playerEntity.getHeldObject() != null /*Forbid digging while holding object*/) return;
         WorldServer world = mcServer.getDimensionWorld(playerEntity.dimension);
-        if(playerActionPacket.action == PacketPlayerAction.ACTION_DROP_ITEM_SINGLE) {
-            // Drop single item
-            playerEntity.dropCurrentItem(false);
-            return;
-        }else if(playerActionPacket.action == PacketPlayerAction.ACTION_DROP_ITEM_STACK) {
-            // Drop full stack
-            playerEntity.dropCurrentItem(true);
-            return;
-        }else if(playerActionPacket.action == PacketPlayerAction.ACTION_PICK_BLOCK) {
-            // Pick Block
-            playerEntity.pickBlock(x, y, z);
-            return;
+        switch (playerActionPacket.action) {
+            case PacketPlayerAction.ACTION_DROP_ITEM_SINGLE:
+                // Drop single item
+                playerEntity.dropCurrentItem(false);
+                return;
+            case PacketPlayerAction.ACTION_DROP_ITEM_STACK:
+                // Drop full stack
+                playerEntity.dropCurrentItem(true);
+                return;
+            case PacketPlayerAction.ACTION_PICK_BLOCK:
+                // Pick Block
+                playerEntity.pickBlock(x, y, z, false);
+                return;
+            case PacketPlayerAction.ACTION_PICK_BLOCK_FULLY:
+                // Pick Block Fully
+                playerEntity.pickBlock(x, y, z, true);
+                return;
         }
 
         // Check player distance
