diff --git a/game/client/build.gradle.kts b/game/client/build.gradle.kts
index 78a61ac68..c3617418e 100644
--- a/game/client/build.gradle.kts
+++ b/game/client/build.gradle.kts
@@ -23,22 +23,6 @@ repositories {
         }
         metadataSources { artifact() }
     }
-    ivy {
-        url = uri("https://github.com/Better-than-Adventure")
-        patternLayout {
-            artifact("[organisation]/releases/download/[revision]/[module]-bta-[revision].jar")
-            m2Compatible
-        }
-        metadataSources { artifact() }
-    }
-    ivy {
-        url = uri("https://github.com/Better-than-Adventure")
-        patternLayout {
-            artifact("[organisation]/releases/download/[revision]/brigadier-[revision].jar")
-            m2Compatible
-        }
-        metadataSources { artifact() }
-    }
 }
 
 dependencies {
@@ -60,7 +44,7 @@ dependencies {
     implementation(project(":util:logging"))?.let { include(it) }
     // </core dependencies>
 
-    implementation("legacy-lwjgl3:legacy-lwjgl3:1.0.4")?.let { include(it) }
+    implementation("com.github.Better-than-Adventure:legacy-lwjgl3:1.0.5")?.let { include(it) }
 
     implementation("org.apache-extras.beanshell:bsh:2.0b6")?.let { include(it) }
     implementation("com.deepoove:codehighlight:1.0.3")?.let { include(it) }
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 570704706..7346f5a25 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
@@ -250,7 +250,7 @@ public class PlayerLocalMultiplayer extends PlayerLocal implements Player.Player
     	data[2] = (byte) (rotationLockVertical != null ? rotationLockVertical.getId() : -1);
     	data[3] = (byte) (placementModeOverride != null ? placementModeOverride.index() : -1);
     	
-    	sendQueue.addToSendQueue(new PacketCustomPayload("BTA|RotationLock", data));
+    	sendQueue.addToSendQueue(new PacketCustomPayload(PacketCustomPayload.CHANNEL_ROTATION_LOCK, data));
     }
     
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenWandMobPicker.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenWandMobPicker.java
index 806789c46..d79342dfc 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenWandMobPicker.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenWandMobPicker.java
@@ -58,7 +58,7 @@ public class ScreenWandMobPicker extends Screen {
                         if (!mc.currentWorld.isClientSide) {
                             wand.getData().putString("monster", mobId);
                         } else {
-                            mc.getSendQueue().addToSendQueue(new PacketCustomPayload("BTA|WandMonster", mobId.getBytes(StandardCharsets.UTF_8)));
+                            mc.getSendQueue().addToSendQueue(new PacketCustomPayload(PacketCustomPayload.CHANNEL_WAND_MONSTER, mobId.getBytes(StandardCharsets.UTF_8)));
                         }
                     }
                     shouldClose = true;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenFlagEditor.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenFlagEditor.java
index e1f9ba18d..b14381f9c 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenFlagEditor.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenFlagEditor.java
@@ -1,5 +1,6 @@
 package net.minecraft.client.gui.container;
 
+import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.client.gui.ClickableLabelElement;
 import net.minecraft.client.gui.DrawableSurfaceElement;
@@ -20,18 +21,24 @@ import net.minecraft.core.net.packet.PacketCustomPayload;
 import net.minecraft.core.player.inventory.menu.MenuFlag;
 import net.minecraft.core.util.helper.MathHelper;
 
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
 public class ScreenFlagEditor
     extends ScreenContainerAbstract
     implements IDrawableSurface<Byte>
 {
     private final TileEntityFlag flagEntity;
     private final int CANVAS_SCALE = 4;
-    private final int CANVAS_WIDTH = 24;
-    private final int CANVAS_HEIGHT = 16;
+    private final int CANVAS_WIDTH = TileEntityFlag.CANVAS_WIDTH;
+    private final int CANVAS_HEIGHT = TileEntityFlag.CANVAS_HEIGHT;
     private int xLast = 0;
     private int yLast = 0;
     private int mouseButton;
 
+    private int tickCount = 0;
+
     private boolean isDrawing = false;
 
     private int canvasX = 0;
@@ -198,6 +205,22 @@ public class ScreenFlagEditor
         }
     }
 
+    @Override
+    public void tick() {
+        tickCount++;
+        if(mc.currentWorld.isClientSide && (tickCount % 40 == 0)) {
+            sendUpdatePacket();
+        }
+    }
+
+    @Override
+    public void removed() {
+        super.removed();
+        if(mc.currentWorld.isClientSide) {
+            sendUpdatePacket();
+        }
+    }
+
     @Override
     protected void buttonClicked(ButtonElement button)
     {
@@ -210,6 +233,9 @@ public class ScreenFlagEditor
         }
         if (button.id == 50) {
             flagEntity.setFlipped(!flagEntity.getFlipped());
+            if(mc.currentWorld.isClientSide) {
+                sendUpdatePacket();
+            }
         }
         if (button.id >= 100 && button.id < 103)
         {
@@ -410,10 +436,6 @@ public class ScreenFlagEditor
     {
         if (eventKey == Keyboard.KEY_ESCAPE || mc.gameSettings.keyInventory.isKeyboardKey(eventKey) || eventKey == Keyboard.KEY_BACK)
         {
-    		// Flag packet needs to be sent before the close screen packet is sent!
-    		if(mc.currentWorld.isClientSide) {
-    			mc.getSendQueue().addToSendQueue(new PacketCustomPayload("BTA|Flag", flagEntity.flagColors));
-    		}
             mc.thePlayer.closeScreen();
         }
 
@@ -461,4 +483,17 @@ public class ScreenFlagEditor
         flagEntity.isDirty = true;
         return true;
     }
+
+    private static final ByteBuffer flagBuffer = ByteBuffer.allocate(1 + TileEntityFlag.CANVAS_HEIGHT * TileEntityFlag.CANVAS_WIDTH).order(ByteOrder.LITTLE_ENDIAN);
+    public void sendUpdatePacket() {
+        flagBuffer.clear();
+
+        byte header = 0;
+        if (flagEntity.flipped) header |= 0b0000_0001;
+
+        flagBuffer.put(header);
+        flagBuffer.put(flagEntity.flagColors);
+
+        mc.getSendQueue().addToSendQueue(new PacketCustomPayload(PacketCustomPayload.CHANNEL_FLAG, (ByteBuffer) flagBuffer.flip()));
+    }
 }
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 0c3922518..43b57c0dd 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
@@ -819,7 +819,7 @@ public class HudIngame extends Gui
     public void drawChat(int width, int height, int sp)
     {
         if (mc.gameSettings.chatVisibility.value == ChatVisibility.NEVER_SHOW) return;
-        if(mc.currentScreen instanceof ScreenChat && ((ScreenChat) mc.currentScreen).message.startsWith("/")) return;
+//        if(mc.currentScreen instanceof ScreenChat && ((ScreenChat) mc.currentScreen).message.startsWith("/")) return;
         int linesToShow = 10;
         boolean ignoreFadeout = false;
         if (mc.currentScreen instanceof ScreenChat)
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/BooleanOptionComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/BooleanOptionComponent.java
index 588159501..52da09e07 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/BooleanOptionComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/BooleanOptionComponent.java
@@ -2,6 +2,7 @@ package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.SwitchElement;
+import net.minecraft.client.option.Option;
 import net.minecraft.client.option.OptionBoolean;
 import net.minecraft.client.render.window.CursorShape;
 
@@ -16,6 +17,7 @@ public class BooleanOptionComponent
         super("options." + option.name);
 
         this.option = option;
+        this.option.addCallback(__ -> onChange());
         this.button = new SwitchElement(0, 0, 0, 150, 20, this.option.value, "", "");
         this.button.setOn(this.option.value);
         this.button.displayString = this.option.getDisplayStringValue();
@@ -24,15 +26,13 @@ public class BooleanOptionComponent
     @Override
     public void resetValue() {
         option.set(option.getDefaultValue());
-        this.button.setOn(this.option.value);
-        this.button.displayString = this.option.getDisplayStringValue();
         option.onUpdate();
+        onChange();
     }
 
     @Override
     public void init(Minecraft mc){
-        this.button.setOn(option.value);
-        this.button.displayString = this.option.getDisplayStringValue();
+        onChange();
     }
 
     @Override
@@ -45,6 +45,10 @@ public class BooleanOptionComponent
     {
         this.option.toggle();
         this.option.onUpdate();
+        onChange();
+    }
+
+    protected void onChange() {
         this.button.setOn(this.option.value);
         this.button.displayString = this.option.getDisplayStringValue();
     }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/DifficultyOptionComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/DifficultyOptionComponent.java
index 64924c587..ef304cd73 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/DifficultyOptionComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/DifficultyOptionComponent.java
@@ -15,26 +15,27 @@ public class DifficultyOptionComponent extends ButtonComponent {
     public DifficultyOptionComponent(OptionEnum<Difficulty> difficultyOption) {
         super("options." + difficultyOption.name);
         option = difficultyOption;
+        option.addCallback(__ -> onChanged());
         this.slider = new IntegerSliderElement(0, 0, 0, 150, 20, option);
     }
 
     @Override
     protected void buttonClicked(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
         this.slider.mouseClicked(mc, this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
-        this.slider.displayString = getDisplayString();
+        onChanged();
         this.option.onUpdate();
     }
 
     @Override
     protected void buttonDragged(int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
-        this.slider.displayString = getDisplayString();
+        onChanged();
         this.option.onUpdate();
     }
 
     @Override
     protected void buttonReleased(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
         this.slider.mouseReleased(this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
-        this.slider.displayString = getDisplayString();
+        onChanged();
         this.option.onUpdate();
     }
 
@@ -60,13 +61,13 @@ public class DifficultyOptionComponent extends ButtonComponent {
         if (!canSetDifficulty()) {
             slider.enabled = false;
             slider.sliderValue = Difficulty.NORMAL.id();
-            this.slider.displayString = getDisplayString();
+            onChanged();
             return;
         }
         slider.enabled = true;
         option.set(mc.currentWorld.getDifficulty());
         slider.sliderValue = option.value.id();
-        this.slider.displayString = getDisplayString();
+        onChanged();
     }
 
     @Override
@@ -81,6 +82,11 @@ public class DifficultyOptionComponent extends ButtonComponent {
         boolean canSet = canSetDifficulty();
         return !canSet || mc.currentWorld.getDifficulty() == Difficulty.NORMAL;
     }
+
+    protected void onChanged() {
+        this.slider.displayString = getDisplayString();
+    }
+
     protected String getDisplayString() {
         if (!canSetDifficulty()) {
             return I18n.getInstance().translateKey("options.difficulty.locked");
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/FloatOptionComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/FloatOptionComponent.java
index 7d817c0ee..84253fd58 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/FloatOptionComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/FloatOptionComponent.java
@@ -16,6 +16,7 @@ public class FloatOptionComponent
         super("options." + option.name);
 
         this.option = option;
+        this.option.addCallback(__ -> onChanged());
         this.slider = new SliderElement(0, 0, 0, 150, 20, this.option.getDisplayStringValue(), this.option.value);
     }
 
@@ -23,7 +24,7 @@ public class FloatOptionComponent
     protected void buttonClicked(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
         this.slider.mouseClicked(mc, this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
         this.option.set((float) this.slider.sliderValue);
-        this.slider.displayString = this.option.getDisplayStringValue();
+        onChanged();
         this.option.onUpdate();
     }
 
@@ -31,7 +32,7 @@ public class FloatOptionComponent
     protected void buttonDragged(int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
         this.option.set((float) this.slider.sliderValue);
         this.slider.mouseDragged(mc, this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
-        this.slider.displayString = this.option.getDisplayStringValue();
+        onChanged();
         this.option.onUpdate();
     }
 
@@ -39,7 +40,7 @@ public class FloatOptionComponent
     protected void buttonReleased(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
         this.slider.mouseReleased(this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
         this.option.set((float) this.slider.sliderValue);
-        this.slider.displayString = this.option.getDisplayStringValue();
+        onChanged();
         this.option.onUpdate();
     }
 
@@ -64,13 +65,17 @@ public class FloatOptionComponent
     public void resetValue() {
         option.set(option.getDefaultValue());
         slider.sliderValue = option.value;
-        this.slider.displayString = this.option.getDisplayStringValue();
+        onChanged();
         option.onUpdate();
     }
 
     @Override
     public void init(Minecraft mc){
         slider.sliderValue = option.value;
+        onChanged();
+    }
+
+    protected void onChanged() {
         this.slider.displayString = this.option.getDisplayStringValue();
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/FramerateOptionComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/FramerateOptionComponent.java
index c4973a5d8..a16e96ec3 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/FramerateOptionComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/FramerateOptionComponent.java
@@ -14,11 +14,11 @@ public class FramerateOptionComponent extends ToggleableOptionComponent<Integer>
     {
         if (mc.gameSettings.enableVsync.value && mc.gameWindow instanceof GameWindowGLFW) {
         	slider.sliderValue = mc.gameWindow.getFrequency();
-            slider.displayString = this.option.getDisplayStringValue();
+            onChanged();
             slider.enabled = false;
         }else {
             slider.sliderValue = option.value;
-            slider.displayString = this.option.getDisplayStringValue();
+            onChanged();
             slider.enabled = true;
         }
 
@@ -42,6 +42,6 @@ public class FramerateOptionComponent extends ToggleableOptionComponent<Integer>
             slider.sliderValue = mc.gameWindow.getFrequency();
             slider.enabled = false;
         }
-        this.slider.displayString = this.option.getDisplayStringValue();
+        onChanged();
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/IntegerOptionComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/IntegerOptionComponent.java
index 6fe4a74c8..089d67cb0 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/IntegerOptionComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/IntegerOptionComponent.java
@@ -16,6 +16,7 @@ public class IntegerOptionComponent
         super("options." + option.name);
 
         this.option = option;
+        this.option.addCallback(__ -> onChanged());
         this.button = new ButtonElement(0, 0, 0, 150, 20, this.option.getDisplayString());
     }
 
@@ -24,7 +25,7 @@ public class IntegerOptionComponent
     {
         this.option.set(this.option.value + 1);
         this.option.onUpdate();
-        this.button.displayString = this.option.getDisplayString();
+        onChanged();
     }
 
     @Override
@@ -47,13 +48,17 @@ public class IntegerOptionComponent
     @Override
     public void resetValue() {
         option.set(option.getDefaultValue());
-        this.button.displayString = this.option.getDisplayStringValue();
+        onChanged();
         option.onUpdate();
     }
 
+    protected void onChanged() {
+        this.button.displayString = this.option.getDisplayStringValue();
+    }
+
     @Override
     public void init(Minecraft mc){
-        this.button.displayString = this.option.getDisplayStringValue();
+        onChanged();
     }
 
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/ToggleableOptionComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/ToggleableOptionComponent.java
index 1c6785694..8bdc4fa36 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/ToggleableOptionComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/ToggleableOptionComponent.java
@@ -16,6 +16,7 @@ public class ToggleableOptionComponent<E>
         super("options." + option.name);
 
         this.option = option;
+        this.option.addCallback(__ -> onChanged());
         this.slider = new IntegerSliderElement(0, 0, 0, 150, 20, option);
     }
 
@@ -23,27 +24,27 @@ public class ToggleableOptionComponent<E>
     public void resetValue() {
         option.set(option.getDefaultValue());
         slider.sliderValue = option.getValueIndex();
-        this.slider.displayString = this.option.getDisplayStringValue();
+        onChanged();
         option.onUpdate();
     }
 
     @Override
     protected void buttonClicked(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
         this.slider.mouseClicked(mc, this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
-        this.slider.displayString = this.option.getDisplayStringValue();
+        onChanged();
         this.option.onUpdate();
     }
 
     @Override
     protected void buttonDragged(int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
-        this.slider.displayString = this.option.getDisplayStringValue();
+        onChanged();
         this.option.onUpdate();
     }
 
     @Override
     protected void buttonReleased(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
         this.slider.mouseReleased(this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
-        this.slider.displayString = this.option.getDisplayStringValue();
+        onChanged();
         this.option.onUpdate();
     }
 
@@ -66,6 +67,10 @@ public class ToggleableOptionComponent<E>
     @Override
     public void init(Minecraft mc){
         slider.sliderValue = option.getValueIndex();
+        onChanged();
+    }
+
+    protected void onChanged() {
         this.slider.displayString = this.option.getDisplayStringValue();
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/input/MouseInput.java b/game/client/src/main/java/net/minecraft/client/input/MouseInput.java
index 73584950c..94937cac5 100644
--- a/game/client/src/main/java/net/minecraft/client/input/MouseInput.java
+++ b/game/client/src/main/java/net/minecraft/client/input/MouseInput.java
@@ -20,11 +20,15 @@ public class MouseInput {
 	public void grabCursor() {
 		Mouse.setGrabbed(true);
 		Mouse.setCursorPosition(minecraft.resolution.getWidthScreenCoords() / 2, minecraft.resolution.getHeightScreenCoords() / 2);
+		GLFW.glfwPollEvents();
+		Mouse.setCursorPosition(minecraft.resolution.getWidthScreenCoords() / 2, minecraft.resolution.getHeightScreenCoords() / 2);
 	}
 	
 	public void releaseCursor() {
 		Mouse.setGrabbed(false);
 		Mouse.setCursorPosition(minecraft.resolution.getWidthScreenCoords() / 2, minecraft.resolution.getHeightScreenCoords() / 2);
+		GLFW.glfwPollEvents();
+		Mouse.setCursorPosition(minecraft.resolution.getWidthScreenCoords() / 2, minecraft.resolution.getHeightScreenCoords() / 2);
 	}
 	
 	public void update() {
diff --git a/game/client/src/main/java/net/minecraft/client/net/handler/PacketHandlerClient.java b/game/client/src/main/java/net/minecraft/client/net/handler/PacketHandlerClient.java
index b1c14b98e..83ac19875 100644
--- a/game/client/src/main/java/net/minecraft/client/net/handler/PacketHandlerClient.java
+++ b/game/client/src/main/java/net/minecraft/client/net/handler/PacketHandlerClient.java
@@ -53,10 +53,12 @@ import net.minecraft.core.player.gamemode.Gamemode;
 import net.minecraft.core.player.inventory.menu.MenuAbstract;
 import net.minecraft.core.player.inventory.container.ContainerSimple;
 import net.minecraft.core.sound.SoundTypes;
+import net.minecraft.core.util.HardIllegalArgumentException;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.AES;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.RSA;
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.core.world.Explosion;
 import net.minecraft.core.world.ExplosionCannonball;
 import net.minecraft.core.world.ICarriable;
@@ -65,6 +67,7 @@ import net.minecraft.core.world.chunk.ChunkCoordinates;
 import net.minecraft.core.world.data.SynchedEntityData;
 import net.minecraft.core.world.save.LevelData;
 import net.minecraft.core.world.saveddata.SavedDataStorage;
+import net.minecraft.core.world.saveddata.maps.ItemMapSavedData;
 import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.weather.Weathers;
 import org.slf4j.Logger;
@@ -330,6 +333,7 @@ public class PacketHandlerClient extends PacketHandler
         final float yRot = (float) (addPlayerPacket.rotation * 360) / 256F;
         final float xRot = (float) (addPlayerPacket.pitch * 360) / 256F;
         final PlayerRemote playerRemote = new PlayerRemote(this.mc.currentWorld, addPlayerPacket.name, addPlayerPacket.uuid);
+        UUIDHelper.nameToUUIDMap.put(addPlayerPacket.name, addPlayerPacket.uuid);
         playerRemote.playerConfig.config = addPlayerPacket.playerConfig;
         playerRemote.xo = playerRemote.serverPosX = addPlayerPacket.xPosition;
         playerRemote.yo = playerRemote.serverPosY = addPlayerPacket.yPosition;
@@ -1071,7 +1075,7 @@ public class PacketHandlerClient extends PacketHandler
     {
         if (mapdataPacket.itemId == Items.MAP.id)
         {
-            ItemMap.getOrCreateSavedData(mapdataPacket.meta, mapdataPacket.scale, mc.currentWorld).setColors(mapdataPacket.mapData);
+            ItemMap.getOrCreateSavedData(mapdataPacket.meta, mapdataPacket.scale, mc.currentWorld).setColors(mapdataPacket.mapData).setMapWaypoints(mapdataPacket.waypoints);
         }
         else
         {
@@ -1126,9 +1130,20 @@ public class PacketHandlerClient extends PacketHandler
     @Override
     public void handleStatistic(final PacketStatistic statisticPacket)
     {
-        final Stat stat = StatList.getStat(statisticPacket.statID);
-        if (stat != null && stat.clientside) return; // Don't allow server to give client side only stats
-        mc.thePlayer.addStat(StatList.getStat(statisticPacket.statID), statisticPacket.valueChange);
+        NamespaceID id;
+        try {
+            id = NamespaceID.getTemp(statisticPacket.statID);
+        } catch (HardIllegalArgumentException e) {
+            LOGGER.error("Received invalid stat id '{}' from server!", statisticPacket.statID);
+            return;
+        }
+        final Stat stat = StatList.getStat(id);
+        if (stat == null) {
+            LOGGER.error("Could not find stat for id '{}' from server!", id);
+            return;
+        }
+        if (stat.clientside) return; // Don't allow server to give client side only stats
+        mc.thePlayer.addStat(stat, statisticPacket.valueChange);
     }
 
     @Override
@@ -1220,7 +1235,7 @@ public class PacketHandlerClient extends PacketHandler
     
     @Override
     public void handleCustomPayload(PacketCustomPayload customPayloadPacket) {
-        if("BTA|RainbowStart".equals(customPayloadPacket.channel)) {
+        if(PacketCustomPayload.CHANNEL_RAINBOW_START.equals(customPayloadPacket.channel)) {
 //            System.out.printf("b0:%s b1:%s b2:%s b3:%s\n", packet.data[0], packet.data[1], packet.data[2], packet.data[3]);
             int rainbowTicks = Byte.toUnsignedInt(customPayloadPacket.data[0]) << 24 | Byte.toUnsignedInt(customPayloadPacket.data[1]) << 16 | Byte.toUnsignedInt(customPayloadPacket.data[2]) << 8 | Byte.toUnsignedInt(customPayloadPacket.data[3]);
 //            System.out.println("Added rainbow with " + rainbowTicks + " ticks");
diff --git a/game/client/src/main/java/net/minecraft/client/option/Option.java b/game/client/src/main/java/net/minecraft/client/option/Option.java
index bc82d5762..7291ae77c 100644
--- a/game/client/src/main/java/net/minecraft/client/option/Option.java
+++ b/game/client/src/main/java/net/minecraft/client/option/Option.java
@@ -1,13 +1,18 @@
 package net.minecraft.client.option;
 
+import net.minecraft.client.gui.paged.CallbackComponent;
 import net.minecraft.core.lang.I18n;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public abstract class Option<E> {
 
 	public final GameSettings gameSettings;
 	public final String name;
 	public E value;
 	protected final E defaultValue;
+	protected final List<OptionCallback<E>> callbacks = new ArrayList<>();
 
 	public Option(GameSettings gameSettings, String name, E defaultValue) {
 		this.gameSettings = gameSettings;
@@ -21,9 +26,16 @@ public abstract class Option<E> {
 		this.value = value;
 	}
 
+	public void addCallback(OptionCallback<E> callback) {
+		this.callbacks.add(callback);
+	}
+
 	public abstract void parse(String string);
 
 	public void onUpdate() {
+		for (final OptionCallback<E> callback : this.callbacks) {
+			callback.onUpdate(this);
+		}
         gameSettings.optionChanged(this);
     }
 
@@ -49,4 +61,8 @@ public abstract class Option<E> {
 	public E getDefaultValue() {
 		return defaultValue;
 	}
+
+	public static interface OptionCallback<T> {
+		public void onUpdate(Option<T> option);
+	}
 }
diff --git a/game/client/src/main/java/net/minecraft/client/player/controller/PlayerController.java b/game/client/src/main/java/net/minecraft/client/player/controller/PlayerController.java
index 318070a11..b18bf9878 100644
--- a/game/client/src/main/java/net/minecraft/client/player/controller/PlayerController.java
+++ b/game/client/src/main/java/net/minecraft/client/player/controller/PlayerController.java
@@ -4,6 +4,7 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.player.PlayerLocal;
 import net.minecraft.core.InventoryAction;
 import net.minecraft.core.block.Block;
+import net.minecraft.core.block.BlockLogicDoor;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.Entity;
@@ -59,6 +60,7 @@ public abstract class PlayerController {
 				if(!repeat) {
 					sendStartDigPacket(x, y, z, side, xHit, yHit);
 					hitBlock(x, y, z, side, xHit, yHit);
+					setMineBlock(x, y, z);
 				}
 			}
 		}
@@ -99,7 +101,9 @@ public abstract class PlayerController {
 				
 				if(!isMiningBlock(x, y, z)) {
 					sendStartDigPacket(x, y, z, side, xHit, yHit);
-					hitBlock(x, y, z, side, xHit, yHit);
+					if (mc.currentWorld.getBlockLogic(x, y, z, BlockLogicDoor.class) == null) { // "Fixes" issue where at certain angles you can spam hit the top and bottom blocks of the door.
+						hitBlock(x, y, z, side, xHit, yHit);
+					}
 					currentDamage = 0.0f;
 					previousDamage = 0.0f;
 					setMineBlock(x, y, z);
@@ -112,6 +116,7 @@ public abstract class PlayerController {
 				if(currentDamage > 1.0f) {
 					destroyBlock(x, y, z, side, mc.thePlayer);
 					sendDestroyBlockPacket(x, y, z, side, xHit, yHit);
+					setMineBlock(null, null, null);
 					currentDamage = 0.0f;
 					previousDamage = 0.0f;
 					soundDelay = 0;
diff --git a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
index 93f52d515..6f4ff32c7 100644
--- a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
+++ b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
@@ -42,6 +42,7 @@ import net.minecraft.core.world.LevelListener;
 import net.minecraft.core.world.season.Seasons;
 import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.weather.Weathers;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.ARBOcclusionQuery;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL15;
@@ -1805,7 +1806,7 @@ public class RenderGlobal
         }
     }
     @Override
-    public void levelEvent(Player player, int id, int x, int y, int z, int data)
+    public void levelEvent(@Nullable Player player, int id, int x, int y, int z, int data)
     {
         Random random = world.rand;
         switch(id) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererPainting.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererPainting.java
index 8814440d8..4f240d56e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererPainting.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererPainting.java
@@ -26,39 +26,31 @@ public class EntityRendererPainting extends EntityRenderer<EntityPainting>
 
     private void renderArt(Tessellator tessellator, EntityPainting entity, int sizeX, int sizeY, IconCoordinate iconCoordinate) {
         iconCoordinate.parentAtlas.bind();
-        float negCenterX = (float)(-sizeX) / 2.0F;
-        float negCenterY = (float)(-sizeY) / 2.0F;
-        float minZ = -0.5F;
-        float maxZ = 0.5F;
+        final float negCenterX = (float)(-sizeX) / 2.0F;
+        final float negCenterY = (float)(-sizeY) / 2.0F;
+        final float minZ = -0.5F;
+        final float maxZ = 0.5F;
 
-        int tilesX = sizeX / 16;
-        int tilesY = sizeY / 16;
+        final int tilesX = sizeX / 16;
+        final int tilesY = sizeY / 16;
 
         for(int x = 0; x < tilesX; x++)
         {
             for(int y = 0; y < tilesY; y++)
             {
-                float maxX = negCenterX + (float)((x + 1) * 16);
-                float minX = negCenterX + (float)(x * 16);
-                float maxY = negCenterY + (float)((y + 1) * 16);
-                float minY = negCenterY + (float)(y * 16);
+                final float maxX = negCenterX + (float)((x + 1) * 16);
+                final float minX = negCenterX + (float)(x * 16);
+                final float maxY = negCenterY + (float)((y + 1) * 16);
+                final float minY = negCenterY + (float)(y * 16);
                 setupPaintingBrightness(entity, (maxX + minX) / 2.0F, (maxY + minY) / 2.0F);
-                double frontMinU = iconCoordinate.getSubIconU((tilesX - x) / (sizeX/16f));
-                double frontMaxU = iconCoordinate.getSubIconU((tilesX - x - 1) / (sizeX/16f));
-                double frontMinV = iconCoordinate.getSubIconV((tilesY - y) / (sizeY/16f));
-                double frontMaxV = iconCoordinate.getSubIconV((tilesY - y - 1) / (sizeY/16f));
-                double backMinU = paintingBack.getIconUMin();
-                double backMaxU = paintingBack.getIconUMax();
-                double backMinV = paintingBack.getIconVMin();
-                double backMaxV = paintingBack.getIconVMax();
-                double topBottomMinU = paintingBack.getIconUMin();
-                double topBottomMaxU = paintingBack.getIconUMax();
-                double topBottomMinV = paintingBack.getSubIconV(1/16f);
-                double topBottomMaxV = paintingBack.getSubIconV(1/16f);
-                double sidesMinU = paintingBack.getSubIconU(1/16f);
-                double sidesMaxU = paintingBack.getSubIconU(1/16f);
-                double sidesMinV = paintingBack.getIconVMin();
-                double sidesMaxV = paintingBack.getIconVMax();
+                final double frontMinU = iconCoordinate.getSubIconU((tilesX - x) / (sizeX/16f));
+                final double frontMaxU = iconCoordinate.getSubIconU((tilesX - x - 1) / (sizeX/16f));
+                final double frontMinV = iconCoordinate.getSubIconV((tilesY - y) / (sizeY/16f));
+                final double frontMaxV = iconCoordinate.getSubIconV((tilesY - y - 1) / (sizeY/16f));
+                final double backMinU = paintingBack.getIconUMin();
+                final double backMaxU = paintingBack.getIconUMax();
+                final double backMinV = paintingBack.getIconVMin();
+                final double backMaxV = paintingBack.getIconVMax();
                 tessellator.startDrawingQuads();
                 tessellator.setNormal(0.0F, 0.0F, -1F);
                 tessellator.addVertexWithUV(maxX, minY, minZ, frontMaxU, frontMinV);
@@ -70,33 +62,38 @@ public class EntityRendererPainting extends EntityRenderer<EntityPainting>
                 tessellator.addVertexWithUV(minX, maxY, maxZ, backMaxU, backMinV);
                 tessellator.addVertexWithUV(minX, minY, maxZ, backMaxU, backMaxV);
                 tessellator.addVertexWithUV(maxX, minY, maxZ, backMinU, backMaxV);
+
                 if (y == tilesY - 1){
                     tessellator.setNormal(0.0F, 1.0F, 0.0F);
-                    tessellator.addVertexWithUV(maxX, maxY, minZ, topBottomMinU, topBottomMinV);
-                    tessellator.addVertexWithUV(minX, maxY, minZ, topBottomMaxU, topBottomMinV);
-                    tessellator.addVertexWithUV(minX, maxY, maxZ, topBottomMaxU, topBottomMaxV);
-                    tessellator.addVertexWithUV(maxX, maxY, maxZ, topBottomMinU, topBottomMaxV);
+                    final double subV = paintingBack.getSubIconV(1 / 16f);
+                    tessellator.addVertexWithUV(minX, maxY, minZ, backMaxU, backMinV);
+                    tessellator.addVertexWithUV(minX, maxY, maxZ, backMaxU, subV);
+                    tessellator.addVertexWithUV(maxX, maxY, maxZ, backMinU, subV);
+                    tessellator.addVertexWithUV(maxX, maxY, minZ, backMinU, backMinV);
                 }
                 if (y == 0){
                     tessellator.setNormal(0.0F, -1F, 0.0F);
-                    tessellator.addVertexWithUV(maxX, minY, maxZ, topBottomMinU, topBottomMinV);
-                    tessellator.addVertexWithUV(minX, minY, maxZ, topBottomMaxU, topBottomMinV);
-                    tessellator.addVertexWithUV(minX, minY, minZ, topBottomMaxU, topBottomMaxV);
-                    tessellator.addVertexWithUV(maxX, minY, minZ, topBottomMinU, topBottomMaxV);
+                    final double subV = paintingBack.getSubIconV(15 / 16f);
+                    tessellator.addVertexWithUV(minX, minY, minZ, backMaxU, subV);
+                    tessellator.addVertexWithUV(maxX, minY, minZ, backMinU, subV);
+                    tessellator.addVertexWithUV(maxX, minY, maxZ, backMinU, backMaxV);
+                    tessellator.addVertexWithUV(minX, minY, maxZ, backMaxU, backMaxV);
                 }
                 if (x == tilesX - 1){
                     tessellator.setNormal(-1F, 0.0F, 0.0F);
-                    tessellator.addVertexWithUV(maxX, maxY, maxZ, sidesMaxU, sidesMinV);
-                    tessellator.addVertexWithUV(maxX, minY, maxZ, sidesMaxU, sidesMaxV);
-                    tessellator.addVertexWithUV(maxX, minY, minZ, sidesMinU, sidesMaxV);
-                    tessellator.addVertexWithUV(maxX, maxY, minZ, sidesMinU, sidesMinV);
+                    final double subU = paintingBack.getSubIconU(1 / 16f);
+                    tessellator.addVertexWithUV(maxX, maxY, maxZ, backMinU, backMinV);
+                    tessellator.addVertexWithUV(maxX, minY, maxZ, backMinU, backMaxV);
+                    tessellator.addVertexWithUV(maxX, minY, minZ, subU, backMaxV);
+                    tessellator.addVertexWithUV(maxX, maxY, minZ, subU, backMinV);
                 }
                 if (x == 0){
                     tessellator.setNormal(1.0F, 0.0F, 0.0F);
-                    tessellator.addVertexWithUV(minX, maxY, minZ, sidesMaxU, sidesMinV);
-                    tessellator.addVertexWithUV(minX, minY, minZ, sidesMaxU, sidesMaxV);
-                    tessellator.addVertexWithUV(minX, minY, maxZ, sidesMinU, sidesMaxV);
-                    tessellator.addVertexWithUV(minX, maxY, maxZ, sidesMinU, sidesMinV);
+                    final double subU = paintingBack.getSubIconU(15 / 16f);
+                    tessellator.addVertexWithUV(minX, maxY, maxZ, subU, backMinV);
+                    tessellator.addVertexWithUV(minX, maxY, minZ, backMaxU, backMinV);
+                    tessellator.addVertexWithUV(minX, minY, minZ, backMaxU, backMaxV);
+                    tessellator.addVertexWithUV(minX, minY, maxZ, subU, backMaxV);
                 }
                 tessellator.draw();
             }
diff --git a/game/client/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java b/game/client/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java
index edf66c196..7ec56b827 100644
--- a/game/client/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java
+++ b/game/client/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java
@@ -2,6 +2,7 @@ package net.minecraft.client.render.window;
 
 import static org.lwjgl.BufferUtils.createByteBuffer;
 import static org.lwjgl.glfw.GLFW.*;
+import static org.lwjgl.system.MemoryUtil.NULL;
 
 import java.awt.*;
 import java.awt.image.BufferedImage;
@@ -317,15 +318,17 @@ public class GameWindowGLFW implements GameWindow {
 
     @Override
     public int getFrequency() {
-        GLFWVidMode vidMode = glfwGetVideoMode(window);
-        if (vidMode != null) {
-            return vidMode.refreshRate();
-        } else {
-            int x = windowPosX + windowWidth / 2;
-            int y = windowPosY + windowHeight / 2;
-            MonitorInfo monitor = getMonitorAt(x, y);
-            return monitor.refreshRate;
+        final long monitor = glfwGetWindowMonitor(window);
+        if (monitor != NULL) {
+            final GLFWVidMode vidMode = glfwGetVideoMode(monitor);
+            if (vidMode != null) {
+                return vidMode.refreshRate();
+            }
         }
+        int x = windowPosX + windowWidth / 2;
+        int y = windowPosY + windowHeight / 2;
+        final MonitorInfo info = getMonitorAt(x, y);
+        return info.refreshRate;
     }
 
     @Override
diff --git a/game/client/src/main/resources/assets/minecraft/textures/item/ore_raw_gold.png b/game/client/src/main/resources/assets/minecraft/textures/item/ore_raw_gold.png
index a28502f0e..0b07c074f 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/item/ore_raw_gold.png and b/game/client/src/main/resources/assets/minecraft/textures/item/ore_raw_gold.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/item/ore_raw_iron.png b/game/client/src/main/resources/assets/minecraft/textures/item/ore_raw_iron.png
index d700f412b..d6852aedd 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/item/ore_raw_iron.png and b/game/client/src/main/resources/assets/minecraft/textures/item/ore_raw_iron.png differ
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java
index 6033321de..d857d93e2 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java
@@ -91,6 +91,15 @@ public class BlockLogicBed extends BlockLogic {
 
 	@Override
 	public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) {
+		removeOtherHalf(world, x, y, z);
+	}
+
+	@Override
+	public void onBlockRemoved(final World world, final int x, final int y, final int z, final int data) {
+		removeOtherHalf(world, x, y, z);
+	}
+
+	protected void removeOtherHalf(final World world, final int x, final int y, final int z) {
 		int metadata = world.getBlockMetadata(x, y, z);
 		int direction = getDirection(metadata);
 		if(isBlockFootOfBed(metadata)) {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicDoor.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDoor.java
index 2615e2e83..db5b15bdb 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicDoor.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicDoor.java
@@ -61,6 +61,7 @@ public class BlockLogicDoor extends BlockLogic implements IPaintable
             } else {
                 world.setBlockMetadataWithNotify(x, y + 1, z, meta | MASK_OPENED);
             }
+            world.playBlockEvent(LevelListener.EVENT_DOOR_SOUND, x, y, z, 0);
         }
     }
 
@@ -229,7 +230,20 @@ public class BlockLogicDoor extends BlockLogic implements IPaintable
             }
         }
     }
-    
+
+    @Override
+    public void onBlockRemoved(final World world, final int x, final int y, final int z, final int data) {
+        if (isTop) {
+            if (world.getBlockLogic(x, y - 1, z, BlockLogicDoor.class) != null) {
+                world.setBlockWithNotify(x, y - 1, z, 0);
+            }
+        } else {
+            if (world.getBlockLogic(x, y + 1, z, BlockLogicDoor.class) != null) {
+                world.setBlockWithNotify(x, y + 1, z, 0);
+            }
+        }
+    }
+
     @Override
 	public void animationTick(World world, int x, int y, int z, Random rand)
     {
diff --git a/game/core/src/main/java/net/minecraft/core/block/Blocks.java b/game/core/src/main/java/net/minecraft/core/block/Blocks.java
index 5ca68761e..db6111b82 100644
--- a/game/core/src/main/java/net/minecraft/core/block/Blocks.java
+++ b/game/core/src/main/java/net/minecraft/core/block/Blocks.java
@@ -121,22 +121,22 @@ public final class Blocks {
         .withTags(BlockTags.CAVES_CUT_THROUGH, BlockTags.MINEABLE_BY_PICKAXE);
 
     public static final Block<?> STONE_CARVED = register("stone.carved", "minecraft:block/stone_carved", 40, (b) -> new BlockLogic(b, Material.stone))
-        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledStats()
         .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
     public static final Block<?> GRANITE_CARVED = register("granite.carved", "minecraft:block/granite_carved", 41, (b) -> new BlockLogic(b, Material.granite))
-        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledStats()
         .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
     public static final Block<?> LIMESTONE_CARVED = register("limestone.carved", "minecraft:block/limestone_carved", 42, (b) -> new BlockLogic(b, Material.limestone))
-        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledStats()
         .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
     public static final Block<?> BASALT_CARVED = register("basalt.carved", "minecraft:block/basalt_carved", 43, (b) -> new BlockLogic(b, Material.basalt))
-        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withSound(BlockSounds.STONE).withHardness(1.0F).withBlastResistance(10F).withDisabledStats()
         .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
     public static final Block<?> PERMAFROST_CARVED = register("permafrost.carved", "minecraft:block/permafrost_carved", 44, (b) -> new BlockLogic(b, Material.permafrost))
-        .withSound(BlockSounds.PERMAFROST).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withSound(BlockSounds.PERMAFROST).withHardness(1.0F).withBlastResistance(10F).withDisabledStats()
         .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
     public static final Block<?> NETHERRACK_CARVED = register("netherrack.carved", "minecraft:block/netherrack_carved", 45, (b) -> new BlockLogic(b, Material.netherrack))
-        .withSound(BlockSounds.STONE).withHardness(2.0F).withBlastResistance(10F).withDisabledStats()
+        .withSound(BlockSounds.STONE).withHardness(0.4F).withBlastResistance(1F).withDisabledStats()
         .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
 
     public static final Block<?> PLANKS_OAK = register("planks.oak", "minecraft:block/planks_oak", 50, BlockLogicPlanks::new)
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 21a1e1195..3863e4ff5 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
@@ -19,8 +19,8 @@ import org.jetbrains.annotations.Nullable;
 public class TileEntityFlag extends TileEntity
     implements Container
 {
-    public final int CANVAS_WIDTH = 24;
-    public final int CANVAS_HEIGHT = 16;
+    public static final int CANVAS_WIDTH = 24;
+    public static final int CANVAS_HEIGHT = 16;
     public boolean isDirty = true; // Used by flag renderer to check if color data has changed at all
     public int colorHash = 0xFFFFFFFF; // Used by flag renderer to quickly check if color data isn't the same
     public int activeDyes = 0; // Used by flag renderer to quickly check if dye data isn't the same
@@ -202,8 +202,8 @@ public class TileEntityFlag extends TileEntity
             {
                 ItemStack stack = items[index];
                 items[index] = null;
-                setChanged();
                 itemsChanges();
+                setChanged();
                 return stack;
             }
             else
@@ -213,8 +213,8 @@ public class TileEntityFlag extends TileEntity
                 {
                     items[index] = null;
                 }
-                setChanged();
                 itemsChanges();
+                setChanged();
                 return splitStack;
             }
         }
@@ -234,8 +234,8 @@ public class TileEntityFlag extends TileEntity
     {
         index -= 36; // This seems so wrong and will almost certainly cause an issue at some point
         items[index] = stack;
-        setChanged();
         itemsChanges();
+        setChanged();
     }
 
     private void itemsChanges() {
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java b/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java
index 25e249c0c..aff3a6fc2 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityFallingBlock.java
@@ -27,6 +27,8 @@ public class EntityFallingBlock extends Entity
         super(world);
         carriedBlock = new CarriedBlock(this, Blocks.SAND, 0, null);
         fallTime = 0;
+        setSize(1F, 1F);
+        heightOffset = bbHeight / 2.0F;
     }
 
     public EntityFallingBlock(World world, double x, double y, double z, int blockId, int blockMeta, @Nullable TileEntity tileEntity) {
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java b/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java
index ed9e9b0f7..f10457f4a 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java
@@ -149,8 +149,8 @@ public class EntityPainting extends Entity
             updateCounter = 0;
             if(!canStay())
             {
-                remove();
                 drop();
+                remove();
             }
         }
     }
@@ -226,12 +226,13 @@ public class EntityPainting extends Entity
     {
         if(!removed && !world.isClientSide)
         {
-            remove();
             markHurt();
             if (!(entity instanceof Player) || ((Player) entity).getGamemode().dropBlockOnBreak())
             {
                 drop();
+                remove();
             }
+            remove();
             world.playBlockSoundEffect(null, this.x, this.y + heightOffset, this.z, Blocks.PLANKS_OAK, EnumBlockSoundEffectType.MINE);
         }
         return true;
@@ -279,8 +280,8 @@ public class EntityPainting extends Entity
     {
         if(!world.isClientSide && xd * xd + yd * yd + zd * zd > 0.0D)
         {
-            remove();
             drop();
+            remove();
         }
     }
 
@@ -289,12 +290,13 @@ public class EntityPainting extends Entity
     {
         if(!world.isClientSide && x * x + y * y + z * z > 0.0D)
         {
-            remove();
             drop();
+            remove();
         }
     }
 
     protected void drop() {
+        if (this.removed) return;
         final Direction d;
         switch (direction) {
             case 0: {
@@ -321,6 +323,7 @@ public class EntityPainting extends Entity
         this.world.entityJoinedWorld(new EntityItem(this.world, x, y, z, new ItemStack(Items.PAINTING)));
         if (getBorderStack() != null){
             this.world.entityJoinedWorld(new EntityItem(this.world, x, y, z, getBorderStack()));
+            setStack(null);
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/AmbientCreature.java b/game/core/src/main/java/net/minecraft/core/entity/animal/AmbientCreature.java
index bdb36ebb3..e19a16f40 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/AmbientCreature.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/AmbientCreature.java
@@ -1,4 +1,4 @@
 package net.minecraft.core.entity.animal;
 
-public interface AmbientCreature extends Creature{
+public interface AmbientCreature {
 }
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 befe891c9..b4d665964 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
@@ -57,6 +57,7 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.ICarriable;
+import net.minecraft.core.world.SpawnerMobs;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.ChunkCoordinates;
 import net.minecraft.core.world.chunk.provider.IChunkProvider;
@@ -1201,6 +1202,11 @@ public abstract class Player
             	sendStatusMessage(I18n.getInstance().translateKey("bed.noSleep"));
                 return EnumSleepStatus.NOT_POSSIBLE_NOW;
             }
+
+            if (SpawnerMobs.isUnsafeToSleep(world, this)) {
+                sendStatusMessage(I18n.getInstance().translateKey("bed.unsafeToSleep"));
+                return EnumSleepStatus.NOT_SAFE;
+            }
         }
         setPlayerSleeping(x, y, z);
         return EnumSleepStatus.OK;
@@ -1650,7 +1656,7 @@ public abstract class Player
 		//Find item with lowest stack size in inventory
 		int itemSlot = -1;
 		int stackSize = -1;
-		for(int i=9; i < 36; i++) {
+		for(int i=0; i < 36; i++) {
 			ItemStack stack = inventory.getItem(i);
 			if(stack != null && stack.itemID == selectItem.itemID && stack.getMetadata() == selectItem.getMetadata() && stack.getData().equals(selectItem.getData())) {
 				if(stackSize == -1 || stack.stackSize < stackSize) {
diff --git a/game/core/src/main/java/net/minecraft/core/enums/EnumSleepStatus.java b/game/core/src/main/java/net/minecraft/core/enums/EnumSleepStatus.java
index 05481f3d2..67701e3d1 100644
--- a/game/core/src/main/java/net/minecraft/core/enums/EnumSleepStatus.java
+++ b/game/core/src/main/java/net/minecraft/core/enums/EnumSleepStatus.java
@@ -1,5 +1,5 @@
 package net.minecraft.core.enums;
 
 public enum EnumSleepStatus {
-	OK, NOT_POSSIBLE_HERE, NOT_POSSIBLE_NOW, TOO_FAR_AWAY, DISABLED_BY_GAMERULE, OTHER_PROBLEM;
+	OK, NOT_POSSIBLE_HERE, NOT_POSSIBLE_NOW, TOO_FAR_AWAY, DISABLED_BY_GAMERULE, OTHER_PROBLEM, NOT_SAFE;
 }
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 a68fd0060..a2208d855 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
@@ -300,7 +300,7 @@ public class Item implements ITaggable<Item>, IItemConvertible
         return I18n.getInstance().translateKey(getKey() + ".name");
     }
 
-    public void inventoryTick(ItemStack itemstack, World world, Entity entity, int i, boolean flag)
+    public void inventoryTick(ItemStack itemstack, World world, Entity entity, int slotId, boolean flag)
     {
     }
 
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 645c306a7..d950b8f5f 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
@@ -56,6 +56,8 @@ public class ItemDoorPainted extends ItemDoor {
         world.notifyBlocksOfNeighborChange(blockX, blockY, blockZ, doorBlockBottom.id());
         world.notifyBlocksOfNeighborChange(blockX, blockY + 1, blockZ, doorBlockTop.id());
         world.playBlockSoundEffect(player,blockX + 0.5F, blockY + 0.5F, blockZ + 0.5F, doorBlockBottom, EnumBlockSoundEffectType.PLACE);
+        doorBlockBottom.onBlockPlacedByMob(world, blockX, blockY, blockZ, side, player, xPlaced, yPlaced);
+        doorBlockTop.onBlockPlacedByMob(world, blockX, blockY + 1, blockZ, side, player, xPlaced, yPlaced);
         itemstack.consumeItem(player);
         return true;
     }
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 19df19513..1937dc62b 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
@@ -29,7 +29,7 @@ public class ItemMap extends Item implements IComplexItem
         super(name, namespaceId, id);
     }
 
-    public static ItemMapSavedData getOrCreateSavedData(short meta, byte scale, World world)
+    public static @NotNull ItemMapSavedData getOrCreateSavedData(short meta, byte scale, World world)
     {
 		String s = String.format("map_%s_scale_%s", meta, scale);
         ItemMapSavedData mapData = (ItemMapSavedData)world.getSavedData(ItemMapSavedData.class, s);
@@ -122,13 +122,16 @@ public class ItemMap extends Item implements IComplexItem
 	@Override
 	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){
-				TileEntityFlag flag = (TileEntityFlag) world.getTileEntity(blockX, blockY, blockZ);
-				boolean canCreateMap = mapData.createNewWaypoint(flag);
-				if(!canCreateMap)
-					player.sendTranslatedChatMessage("flag.full");
-				return canCreateMap;
+			if (hasInitialized(itemstack)) {
+				for (byte scale = 0; scale <= ItemMapSavedData.MAX_SCALE; scale++) {
+					ItemMapSavedData mapData = getOrCreateSavedData((short) itemstack.getMetadata(), scale, world);
+                    TileEntityFlag flag = (TileEntityFlag) world.getTileEntity(blockX, blockY, blockZ);
+                    if (mapData.createNewWaypoint(flag) == ItemMapSavedData.FlagError.FULL) {
+						player.sendTranslatedChatMessage("flag.full");
+						break;
+					}
+                }
+				return true;
 			}
 		}
 		return false;
@@ -309,12 +312,26 @@ public class ItemMap extends Item implements IComplexItem
 	}
 
     @Override
-    public void inventoryTick(ItemStack itemstack, World world, Entity entity, int i, boolean flag)
+    public void inventoryTick(ItemStack itemstack, World world, Entity entity, int slotId, boolean isHeld)
     {
         if(world.isClientSide)
         {
             return;
         }
+		if (hasInitialized(itemstack)) {
+			final byte mapScale = getScale(itemstack);
+			for (byte scale = 0; scale <= ItemMapSavedData.MAX_SCALE; scale++) {
+				final ItemMapSavedData mapData = getOrCreateSavedData((short) itemstack.getMetadata(), scale, world);
+				if(entity instanceof Player) {
+					final Player player = (Player)entity;
+					if (scale == mapScale) mapData.tickCarriedBy(player, itemstack);
+					mapData.tickForWaypoints(player, itemstack);
+				}
+				if(scale == mapScale && isHeld) {
+					update(world, entity, mapData);
+				}
+			}
+		}
         ItemMapSavedData mapData = getOrCreateSavedData(itemstack, world);
         if (mapData != null){
 			if(entity instanceof Player)
@@ -322,7 +339,7 @@ public class ItemMap extends Item implements IComplexItem
 				Player player = (Player)entity;
 				mapData.tickCarriedBy(player, itemstack);
 			}
-			if(flag)
+			if(isHeld)
 			{
 				update(world, entity, mapData);
 			}
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 08d16fb48..0d59e5f00 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
@@ -399,13 +399,13 @@ public final class ItemStack {
         return stackSize + " * " + Item.itemsList[itemID].getKey() + ":" + metadata;
     }
 
-    public void updateAnimation(World world, Entity entity, int i, boolean flag)
+    public void updateAnimation(World world, Entity entity, int slotId, boolean flag)
     {
         if(animationsToGo > 0)
         {
             animationsToGo--;
         }
-        Item.itemsList[itemID].inventoryTick(this, world, entity, i, flag);
+        Item.itemsList[itemID].inventoryTick(this, world, entity, slotId, flag);
     }
 
     public void onCrafting(World world, Player entityplayer)
diff --git a/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryAnimal.java b/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryAnimal.java
index 2e2567967..27d4c3efc 100644
--- a/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryAnimal.java
+++ b/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryAnimal.java
@@ -11,6 +11,7 @@ import net.minecraft.core.net.packet.PacketAddMob;
 import org.jetbrains.annotations.NotNull;
 
 public class NetEntryAnimal<T extends Mob> implements IPacketEntry<T>, ITrackedEntry<T> {
+
     @SuppressWarnings("unchecked")
     @Override
     public @NotNull Class<T> getAppliedClass() {
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketCustomPayload.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketCustomPayload.java
index 4fc4e41e8..b815a0073 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketCustomPayload.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketCustomPayload.java
@@ -3,20 +3,27 @@ package net.minecraft.core.net.packet;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 
 import net.minecraft.core.net.handler.PacketHandler;
+import org.jetbrains.annotations.NotNull;
 
 public class PacketCustomPayload extends Packet {
+	public static final @NotNull String CHANNEL_FLAG = "BTA:Flag";
+	public static final @NotNull String CHANNEL_ROTATION_LOCK = "BTA:RotationLock";
+	public static final @NotNull String CHANNEL_WAND_MONSTER = "BTA:WandMonster";
+	public static final @NotNull String CHANNEL_RAINBOW_START = "BTA:RainbowStart";
+
 	public static final int MAX_CHANNEL_SIZE = 128;
 
 	public String channel;
 	public byte[] data;
-	
+
 	public PacketCustomPayload() {
 		
 	}
 	
-	public PacketCustomPayload(String channel, byte[] data) {
+	public PacketCustomPayload(@NotNull String channel, byte[] data) {
 		this.channel = channel;
 		
 		if(data != null) {
@@ -26,6 +33,20 @@ public class PacketCustomPayload extends Packet {
 			this.data = data;
 		}
 	}
+
+	public PacketCustomPayload(@NotNull String channel, ByteBuffer data) {
+		this.channel = channel;
+
+		if(data != null) {
+			final int remaining = data.remaining();
+			if(remaining > 32768) {
+				throw new IllegalArgumentException("Payload may not be larger than 32k");
+			}
+			byte[] d = new byte[remaining];
+			data.get(d, 0, remaining);
+			this.data = d;
+		}
+	}
 	
 	@Override
 	public void read(DataInputStream in) throws IOException {
diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketStatistic.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketStatistic.java
index 6b76a85e4..a7e0005fd 100644
--- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketStatistic.java
+++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketStatistic.java
@@ -8,7 +8,7 @@ import java.io.*;
 
 public class PacketStatistic extends Packet
 {
-    public NamespaceID statID;
+    public String statID;
     public int valueChange;
 
 
@@ -18,7 +18,7 @@ public class PacketStatistic extends Packet
 
     public PacketStatistic(NamespaceID statID, int change)
     {
-        this.statID = statID;
+        this.statID = statID.toString();
         valueChange = change;
     }
 
@@ -33,11 +33,7 @@ public class PacketStatistic extends Packet
 	public void read(DataInputStream dis)
         throws IOException
     {
-        try {
-            statID = NamespaceID.getTemp(readStringUTF8(dis, Integer.MAX_VALUE));
-        } catch (HardIllegalArgumentException e) {
-            statID = null;
-        }
+        statID = readStringUTF8(dis, Integer.MAX_VALUE);
         valueChange = dis.readByte();
     }
 
@@ -45,7 +41,7 @@ public class PacketStatistic extends Packet
 	public void write(DataOutputStream dos)
         throws IOException
     {
-        writeStringUTF8(statID.toString(), dos);
+        writeStringUTF8(statID, dos);
         dos.writeByte(valueChange);
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/player/Session.java b/game/core/src/main/java/net/minecraft/core/player/Session.java
index e5ff6ca58..abc3fe646 100644
--- a/game/core/src/main/java/net/minecraft/core/player/Session.java
+++ b/game/core/src/main/java/net/minecraft/core/player/Session.java
@@ -16,6 +16,7 @@ public class Session
         this.username = username;
         this.uuid = UUID.fromString(UUIDHelper.untrimUUID(uuid));
         this.sessionId = sessionId;
+        UUIDHelper.nameToUUIDMap.put(this.username, this.uuid);
     }
 
 
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/InventorySorter.java b/game/core/src/main/java/net/minecraft/core/player/inventory/InventorySorter.java
index f736e9617..d2b418fa6 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/InventorySorter.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/InventorySorter.java
@@ -68,7 +68,11 @@ public abstract class InventorySorter {
             final int bId = b.itemID;
 
             if (aId == bId) {
-                return b.stackSize - a.stackSize;
+                if (a.getMetadata() == b.getMetadata()) {
+                    return b.stackSize - a.stackSize;
+                } else {
+                    return a.getMetadata() - b.getMetadata();
+                }
             }
             if (aId < bId) {
                 return -1;
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java
index 6f7dafafd..f1c473276 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerInventory.java
@@ -199,11 +199,11 @@ public class ContainerInventory
 
     public void decrementAnimations()
     {
-        for(int i = 0; i < mainInventory.length; i++)
+        for(int slot = 0; slot < mainInventory.length; slot++)
         {
-            if(mainInventory[i] != null)
+            if(mainInventory[slot] != null)
             {
-                mainInventory[i].updateAnimation(player.world, player, i, currentItem == i);
+                mainInventory[slot].updateAnimation(player.world, player, slot, currentItem == slot);
             }
         }
 
diff --git a/game/core/src/main/java/net/minecraft/core/sound/SoundTypes.java b/game/core/src/main/java/net/minecraft/core/sound/SoundTypes.java
index fafaca869..86511985b 100644
--- a/game/core/src/main/java/net/minecraft/core/sound/SoundTypes.java
+++ b/game/core/src/main/java/net/minecraft/core/sound/SoundTypes.java
@@ -5,7 +5,9 @@ import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParseException;
 import com.google.gson.JsonParser;
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.net.packet.PacketSyncIDs;
+import org.slf4j.Logger;
 
 import java.io.InputStream;
 import java.util.HashMap;
@@ -13,37 +15,39 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 public class SoundTypes {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static final Map<Integer, String> idToSoundNameMap = new HashMap<>();
 	private static final Map<String, Integer> soundNameToIdMap = new HashMap<>();
-	
+	private static final String format = "/assets/%s/sounds/sounds.json";
 	private static int idCount = 0;
 	
 	/**
 	 * Required for any sound that is supposed to be played by the server
 	 */
 	public static void registerSounds() {
-		loadSoundsJson("/assets/minecraft/sounds/sounds.json");
+		loadSoundsJson("minecraft");
 	}
 
-	public static void loadSoundsJson(String path) {
-		JsonObject o;
+	public static void loadSoundsJson(final String namespace) {
+		final JsonObject o;
 		try {
-			o = loadStreamAsElement(SoundTypes.class.getResourceAsStream(path)).getAsJsonObject();
-		} catch (Exception e) {
-			System.err.println("Failed to load '" + path + "' as a json!");
-			e.printStackTrace();
+			o = loadStreamAsElement(SoundTypes.class.getResourceAsStream(String.format(format, namespace))).getAsJsonObject();
+		} catch (final Exception e) {
+            LOGGER.error("Failed to load sounds.json from '{}' as a json object!", namespace, e);
 			return;
 		}
-		for (String s : o.asMap().keySet()) {
-			register(s);
+		final boolean isMC = namespace.equals("minecraft");
+		for (final String s : o.asMap().keySet()) {
+			register(namespace + ":" + s);
+			if (isMC) register(s);
 		}
 	}
 
-	private static JsonElement loadStreamAsElement(InputStream stream) throws JsonParseException {
+	private static JsonElement loadStreamAsElement(final InputStream stream) throws JsonParseException {
 		return JsonParser.parseString(StringUtils.readInputString(stream));
 	}
 
-	public static boolean register(String soundPath) {
+	public static boolean register(final String soundPath) {
 		if(soundPath.length() > PacketSyncIDs.MAX_ID_STRING_SIZE) {
 			throw new RuntimeException("Sound Path is too long: '" + soundPath + "'!");
 		}
@@ -52,7 +56,7 @@ public class SoundTypes {
 			return false;
 		}
 		
-		int id = idCount++;
+		final int id = idCount++;
 		
 		// Sound IDs are sent as short to the client
 		idCount %= 65536;
@@ -66,8 +70,8 @@ public class SoundTypes {
 	/**
 	 * Returns -1 if the given soundPath is not registered! 
 	 */
-	public static int getSoundId(String soundPath) {
-		Integer id = soundNameToIdMap.get(soundPath);
+	public static int getSoundId(final String soundPath) {
+		final Integer id = soundNameToIdMap.get(soundPath);
 		if(id == null) {
 			return -1;
 		}
@@ -77,17 +81,17 @@ public class SoundTypes {
 	 * Returns null if the given id does not exist!
 	 */
 	
-	public static String getSoundById(int id) {
+	public static String getSoundById(final int id) {
 		return idToSoundNameMap.get(id);
 	}
 	
-	public static void setSoundIds(Map<Integer, String> soundIds) {
+	public static void setSoundIds(final Map<Integer, String> soundIds) {
 		idToSoundNameMap.clear();
 		soundNameToIdMap.clear();
 		
-		for(Entry<Integer, String> entry : soundIds.entrySet()) {
-			int id = entry.getKey();
-			String name = entry.getValue();
+		for(final Entry<Integer, String> entry : soundIds.entrySet()) {
+			final int id = entry.getKey();
+			final String name = entry.getValue();
 			
 			idToSoundNameMap.put(id, name);
 			soundNameToIdMap.put(name, id);
@@ -98,5 +102,4 @@ public class SoundTypes {
 		// TODO Make soundNameToIdMap immutable
 		return idToSoundNameMap;
 	}
-
 }
diff --git a/game/core/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java b/game/core/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java
index efe5bfa2d..2930106f7 100644
--- a/game/core/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java
+++ b/game/core/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java
@@ -15,7 +15,7 @@ public class UUIDHelper {
     private static final String urlUUID = "https://api.mojang.com/users/profiles/minecraft/";
 
     private static final JsonParser jsonParser = new JsonParser();
-    private static final Map<String, UUID> nameToUUIDMap = new HashMap<>();
+    public static final Map<String, UUID> nameToUUIDMap = new HashMap<>();
 
     public static boolean isUUID(String usernameOrUUID) {
         return usernameOrUUID.length() == 36 || usernameOrUUID.length() == 32;
@@ -58,6 +58,9 @@ public class UUIDHelper {
         }).start();
     }
     public static @Nullable UUID getUUIDFromName(String username){
+        if (nameToUUIDMap.containsKey(username)) {
+            return nameToUUIDMap.get(username);
+        }
         String string;
         try{
             string = StringUtils.getWebsiteContentAsString(urlUUID + username);
diff --git a/game/core/src/main/java/net/minecraft/core/world/LevelListener.java b/game/core/src/main/java/net/minecraft/core/world/LevelListener.java
index 5bbff7a08..ab05e866d 100644
--- a/game/core/src/main/java/net/minecraft/core/world/LevelListener.java
+++ b/game/core/src/main/java/net/minecraft/core/world/LevelListener.java
@@ -4,6 +4,7 @@ import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.sound.SoundCategory;
+import org.jetbrains.annotations.Nullable;
 
 public interface LevelListener
 {
@@ -79,5 +80,5 @@ public interface LevelListener
 
     void tileEntityChanged(int x, int y, int z, TileEntity tileEntity);
 
-    void levelEvent(Player player, int id, int x, int y, int z, int data);
+    void levelEvent(@Nullable Player player, int id, int x, int y, int z, int data);
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/SpawnerMobs.java b/game/core/src/main/java/net/minecraft/core/world/SpawnerMobs.java
index 47ee135ca..eeb684cc3 100644
--- a/game/core/src/main/java/net/minecraft/core/world/SpawnerMobs.java
+++ b/game/core/src/main/java/net/minecraft/core/world/SpawnerMobs.java
@@ -201,6 +201,84 @@ public final class SpawnerMobs
         }
     }
 
+    public static boolean isUnsafeToSleep(World world, Player player) {
+        if (!world.getGameRuleValue(GameRules.DO_NIGHTMARES)) {
+            return false;
+        }
+
+        if (player.isPlayerSleeping()) {
+            return false;
+        }
+        if (player.getGamemode().isPlayerInvulnerable()) {
+            return false;
+        }
+
+        Class<?>[] entityClasses = nightSpawnEntities;
+        if (entityClasses != null && entityClasses.length != 0) {
+            boolean willSpawnEntity = false;
+            PathFinder pathFinder = new PathFinder(world);
+
+            // Make 20 attempts to find a path
+            int i = 0;
+            while (i < 20 && !willSpawnEntity) {
+                // Get a random location for the path start
+                int x = MathHelper.floor(player.x) + world.rand.nextInt(32) - world.rand.nextInt(32);
+                int z = MathHelper.floor(player.z) + world.rand.nextInt(32) - world.rand.nextInt(32);
+                int y = MathHelper.floor(player.y) + world.rand.nextInt(16) - world.rand.nextInt(16);
+                y = MathHelper.clamp(y, 1, world.getHeightBlocks());
+
+                int spawnY = y;
+
+                // Ensure we have enough space
+                while (spawnY > 2 && !world.isBlockNormalCube(x, spawnY - 1, z)) {
+                    spawnY--;
+                }
+
+                // Make sure we're allowed to spawn in this Y coordinate
+                while (
+                        !canCreatureTypeSpawnAtLocation(MobCategory.monster, world, x, spawnY, z) &&
+                        spawnY < y + 16 &&
+                        spawnY < world.getHeightBlocks()
+                ) {
+                    spawnY++;
+                }
+
+                if (spawnY < y + 16) {
+                    float entityX = x + 0.5f;
+                    float entityY = spawnY;
+                    float entityZ = z + 0.5f;
+
+                    Mob entity;
+                    Class<?> eClass = entityClasses[world.rand.nextInt(entityClasses.length)];
+                    try {
+                        entity = (Mob) eClass.getConstructor(World.class).newInstance(world);
+                    } catch (Exception e) {
+                        LOGGER.error("Exception instancing class '{}'!", eClass.getSimpleName(), e);
+                        return false;
+                    }
+
+                    entity.moveTo(entityX, entityY, entityZ, world.rand.nextFloat() * 360.0f, 0.0f);
+                    if(entity.canSpawnHere())
+                    {
+                        Path pathEntity = pathFinder.findPath(entity, player, 32.0f);
+                        if(pathEntity != null && pathEntity.length > 1)
+                        {
+                            Node pathPoint = pathEntity.last();
+                            boolean isCollisionFree = world.checkBlockCollisionBetweenPoints(Vec3.getTempVec3(player.x, player.y + 1.5f, player.z), Vec3.getTempVec3(pathPoint.x, pathPoint.y + 1.5f, pathPoint.z)) == null;
+                            if(Math.abs(pathPoint.x + 0.5f - player.x) < 1.5 && Math.abs(pathPoint.z + 0.5f - player.z) < 1.5 && Math.abs(pathPoint.y + 0.5f - player.y) < 1.5 && isCollisionFree) {
+                                return true;
+                            }
+                        }
+                    }
+                }
+
+                i++;
+            }
+        }
+
+        return false;
+    }
+
 	public static boolean performSleepSpawning(World world, List<Player> list)
     {
         if (!world.getGameRuleValue(GameRules.DO_NIGHTMARES))
diff --git a/game/core/src/main/java/net/minecraft/core/world/World.java b/game/core/src/main/java/net/minecraft/core/world/World.java
index 129b38da5..d15adc538 100644
--- a/game/core/src/main/java/net/minecraft/core/world/World.java
+++ b/game/core/src/main/java/net/minecraft/core/world/World.java
@@ -3114,10 +3114,10 @@ public class World implements WorldSource {
         playBlockEvent(null, id, x, y, z, data);
     }
 
-    public void playBlockEvent(Player entityplayer, int id, int x, int y, int z, int data)
+    public void playBlockEvent(@Nullable Player player, int id, int x, int y, int z, int data)
     {
         for (LevelListener listener : listeners) {
-            listener.levelEvent(entityplayer, id, x, y, z, data);
+            listener.levelEvent(player, id, x, y, z, data);
         }
 
     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java b/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java
index 92db2c965..5ae8eb4ec 100644
--- a/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java
+++ b/game/core/src/main/java/net/minecraft/core/world/saveddata/maps/ItemMapSavedData.java
@@ -8,7 +8,9 @@ import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
+import net.minecraft.core.world.chunk.ChunkPosition;
 import net.minecraft.core.world.saveddata.SavedData;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.*;
 
@@ -24,7 +26,7 @@ public class ItemMapSavedData extends SavedData
     public List<HoldingPlayer> carriedBy;
     private final Map<Player, HoldingPlayer> carriedByPlayers;
     public List<MapDecoration> decorations;
-    public final int MAX_WAYPOINTS = 16;
+    public final int MAX_WAYPOINTS = 32;
     public List<MapWaypoint> mapWaypoints;
 
     public ItemMapSavedData(String id)
@@ -104,6 +106,18 @@ public class ItemMapSavedData extends SavedData
         tag.put("Waypoints", waypointsList);
     }
 
+    public void tickForWaypoints(Player player, ItemStack stack) {
+        for(MapWaypoint mapWaypoint : mapWaypoints){
+            if(player.distanceToSqr(mapWaypoint.xPos, mapWaypoint.yPos, mapWaypoint.zPos) <= 256D) {
+                if(player.world.getBlockId(mapWaypoint.xPos, mapWaypoint.yPos, mapWaypoint.zPos)!= Blocks.FLAG.id())
+                {
+                    mapWaypoints.remove(mapWaypoint);
+                    break;
+                }
+            }
+        }
+    }
+
     public void tickCarriedBy(Player player, ItemStack stack)
     {
         if(!carriedByPlayers.containsKey(player))
@@ -114,16 +128,6 @@ public class ItemMapSavedData extends SavedData
         }
         decorations.clear();
 
-        for(MapWaypoint mapWaypoint : mapWaypoints){
-            if(player.distanceToSqr(mapWaypoint.xPos, mapWaypoint.yPos, mapWaypoint.zPos) <= 256D) {
-               if(player.world.getBlockId(mapWaypoint.xPos, mapWaypoint.yPos, mapWaypoint.zPos)!= Blocks.FLAG.id())
-                {
-                    mapWaypoints.remove(mapWaypoint);
-                    break;
-                }
-            }
-        }
-
         for(int i = 0; i < carriedBy.size(); i++)
         {
             HoldingPlayer mapinfo1 = carriedBy.get(i);
@@ -153,10 +157,10 @@ public class ItemMapSavedData extends SavedData
         }
     }
 
-    public boolean createNewWaypoint(TileEntityFlag flag)
+    public @NotNull FlagError createNewWaypoint(TileEntityFlag flag)
     {
         if(mapWaypoints.size() >= MAX_WAYPOINTS)
-            return false;
+            return FlagError.FULL;
 
         float xd = (float)(flag.x - (double) x) / (float)(1 << scale);
         float zd = (float)(flag.z - (double) z) / (float)(1 << scale);
@@ -168,7 +172,7 @@ public class ItemMapSavedData extends SavedData
 
         if(xd < (float)(-maxWidth) || zd < (float)(-maxHeight) || xd > (float) maxWidth || zd > (float) maxHeight)
         {
-            return false;
+            return FlagError.OUTSIDE_RANGE;
         }
 
         byte[] colors = new byte[9];
@@ -180,7 +184,7 @@ public class ItemMapSavedData extends SavedData
         }
 
         mapWaypoints.add(new MapWaypoint(xCoord, zCoord, flag.x, flag.y, flag.z, colors));
-        return true;
+        return FlagError.NONE;
     }
 
     public byte[] getMapDataBytes(ItemStack stack, World world, Player player)
@@ -354,4 +358,10 @@ public class ItemMapSavedData extends SavedData
             this.rot = rot;
         }
     }
+
+    public enum FlagError {
+        NONE,
+        FULL,
+        OUTSIDE_RANGE;
+    }
 }
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 316facd76..a5a5e8698 100644
--- a/game/core/src/main/resources/lang/en_US/options.lang
+++ b/game/core/src/main/resources/lang/en_US/options.lang
@@ -181,6 +181,7 @@ options.forceOnscreenKeyboard=Force On Screen Keyboard
 options.enableHolidayTextures=Enable Holiday Textures
 options.dynamicCursor=Dynamic Cursor
 options.enableDevResourceLoading=Developer Resource Loading
+options.enableMultiDrawRendering=Enable Multi-Draw Renderer (experimental!)
 
 options.fov.modification=Contextual FOV Modification
 options.screen.motion.effects=Screen Motion Effects
diff --git a/game/core/src/main/resources/lang/en_US/strings.lang b/game/core/src/main/resources/lang/en_US/strings.lang
index 62d7c905f..a7991f724 100644
--- a/game/core/src/main/resources/lang/en_US/strings.lang
+++ b/game/core/src/main/resources/lang/en_US/strings.lang
@@ -92,6 +92,7 @@ bed.noSleep=You can only sleep at night or during thunderstorms.
 bed.setSpawn=Respawn point set.
 bed.notValid=Your home bed was missing or obstructed.
 bed.noAllowSleeping=Sleeping is disabled.
+bed.unsafeToSleep=It's not safe to sleep here.
 
 sign.image.none=None
 sign.image.arrow_right=Right Arrow
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 9050f318d..57928f434 100644
--- a/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -102,6 +102,7 @@ import net.minecraft.server.world.WorldManager;
 import net.minecraft.server.world.WorldServer;
 import net.minecraft.server.world.WorldServerMulti;
 import net.minecraft.server.world.chunk.provider.ChunkProviderServer;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 
 import java.io.BufferedReader;
@@ -127,6 +128,10 @@ public class MinecraftServer
     public static final String VERSION = Global.VERSION;
     private static MinecraftServer instance;
     public static HashMap<String, Integer> field_6037_b = new HashMap<>();
+
+    public @Nullable Boolean argOffline = null;
+    public @Nullable String argWorld = null;
+
     public NetworkListenThread networkServer;
     public PropertyManager propertyManager;
     public Map<Integer, WorldServer> dimensionWorlds;
@@ -225,7 +230,7 @@ public class MinecraftServer
         LOGGER.info("Loading properties");
         propertyManager = new PropertyManager(new File("server.properties"));
         String s = propertyManager.getStringProperty("server-ip", "");
-        onlineMode = propertyManager.getBooleanProperty("online-mode", true);
+        onlineMode = argOffline == null ? propertyManager.getBooleanProperty("online-mode", true) : !argOffline;
         spawnAnimals = propertyManager.getBooleanProperty("spawn-animals", true);
         spawnHostiles = propertyManager.getBooleanProperty("spawn-monsters", true);
         pvpOn = propertyManager.getBooleanProperty("pvp", true);
@@ -360,7 +365,7 @@ public class MinecraftServer
             entityTrackerMap.put(entry.getKey(), new EntityTrackerImpl(this, entry.getValue()));
         }
         long time = System.nanoTime();
-        String lName = propertyManager.getStringProperty("level-name", "world");
+        String lName = argWorld == null ? propertyManager.getStringProperty("level-name", "world") : argWorld;
         String lSeed = propertyManager.getStringProperty("level-seed", "");
         long randomLong = (new Random()).nextLong();
         if (!lSeed.isEmpty())
@@ -823,14 +828,52 @@ public class MinecraftServer
 
     public static void main(String[] args)
     {
+
+        boolean nogui = false;
+        Boolean offline = null;
+        String world = null;
+
+        int pointer = 0;
+        while (pointer < args.length) {
+            switch (args[pointer]) {
+                case "nogui": // This is the legacy alias for nogui arg
+                case "--nogui": {
+                    nogui = true;
+                    pointer++;
+                    break;
+                }
+                case "--offline": {
+                    offline = true;
+                    pointer++;
+                    break;
+                }
+                case "--world": {
+                    try {
+                        world = args[pointer + 1];
+                        pointer++;
+                    } catch (final Exception e) {
+                        e.printStackTrace();
+                    }
+                    pointer++;
+                    break;
+                }
+                default:
+                    pointer++;
+            }
+        }
+
         try
         {
-            MinecraftServer minecraftserver = new MinecraftServer();
-            if (!java.awt.GraphicsEnvironment.isHeadless() && (args.length == 0 || !args[0].equals("nogui")))
+            MinecraftServer server = new MinecraftServer();
+
+            server.argOffline = offline;
+            server.argWorld = world;
+
+            if (!nogui && !java.awt.GraphicsEnvironment.isHeadless())
             {
-                ServerGui.initGui(minecraftserver);
+                ServerGui.initGui(server);
             }
-            new Thread(minecraftserver, "Server thread").start();
+            new Thread(server, "Server thread").start();
         }
         catch (Exception exception)
         {
diff --git a/game/server/src/main/java/net/minecraft/server/net/PlayerList.java b/game/server/src/main/java/net/minecraft/server/net/PlayerList.java
index 9dc1327af..869dd63f7 100644
--- a/game/server/src/main/java/net/minecraft/server/net/PlayerList.java
+++ b/game/server/src/main/java/net/minecraft/server/net/PlayerList.java
@@ -609,7 +609,7 @@ public class PlayerList
         sendPacketToOtherPlayersAroundPoint(null, x, y, z, radius, dimension, packet);
     }
 
-    public void sendPacketToOtherPlayersAroundPoint(Player player, double x, double y, double z,
+    public void sendPacketToOtherPlayersAroundPoint(@Nullable Player player, double x, double y, double z,
                                                     double radius, int dimension, Packet packet)
     {
         for (PlayerServer otherPlayer : playerEntities) {
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 319a49b98..b39251b7a 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
@@ -45,6 +45,7 @@ import org.slf4j.Logger;
 
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -802,21 +803,27 @@ public class PacketHandlerServer extends PacketHandler
     
     @Override
     public void handleCustomPayload(PacketCustomPayload customPayloadPacket) {
-    	if("BTA|RotationLock".equals(customPayloadPacket.channel)) {
+    	if(PacketCustomPayload.CHANNEL_ROTATION_LOCK.equals(customPayloadPacket.channel)) {
     		if(customPayloadPacket.data.length == 4) {
         		playerEntity.rotationLock = Direction.getDirectionById(customPayloadPacket.data[0]);
         		playerEntity.rotationLockHorizontal = Direction.getDirectionById(customPayloadPacket.data[1]);
         		playerEntity.rotationLockVertical = Direction.getDirectionById(customPayloadPacket.data[2]);
         		playerEntity.placementModeOverride = PlacementMode.get(customPayloadPacket.data[3]);
     		}
-    	}else if("BTA|Flag".equals(customPayloadPacket.channel)) {
-    		if(customPayloadPacket.data.length == 24 * 16 && playerEntity.craftingInventory instanceof MenuFlag) {
+    	}else if(PacketCustomPayload.CHANNEL_FLAG.equals(customPayloadPacket.channel)) {
+    		if(customPayloadPacket.data.length == 1 + (TileEntityFlag.CANVAS_WIDTH * TileEntityFlag.CANVAS_HEIGHT) && playerEntity.craftingInventory instanceof MenuFlag) {
     			MenuFlag menuFlag = (MenuFlag) playerEntity.craftingInventory;
     			TileEntityFlag flag = menuFlag.flag;
 
     			if(flag.owner == null || flag.owner.equals(playerEntity.uuid)) {
                     flag.owner = playerEntity.uuid;
-        			System.arraycopy(customPayloadPacket.data, 0, flag.flagColors, 0, 24 * 16);
+
+                    byte header = customPayloadPacket.data[0];
+
+                    boolean flipped = (header & 0b0000_0001) != 0;
+
+        			System.arraycopy(customPayloadPacket.data, 1, flag.flagColors, 0, TileEntityFlag.CANVAS_WIDTH * TileEntityFlag.CANVAS_HEIGHT);
+                    flag.setFlipped(flipped);
 
         			playerEntity.world.markBlockNeedsUpdate(flag.x, flag.y, flag.z);
     			}else {
@@ -826,7 +833,7 @@ public class PacketHandlerServer extends PacketHandler
     				playerEntity.world.markBlockNeedsUpdate(flag.x, flag.y, flag.z);
     			}
     		}
-    	} else if ("BTA|WandMonster".equals(customPayloadPacket.channel)) {
+    	} else if (PacketCustomPayload.CHANNEL_WAND_MONSTER.equals(customPayloadPacket.channel)) {
             if (playerEntity.getHeldItem() != null && playerEntity.getHeldItem().getItem() == Items.WAND_MONSTER_SPAWNER){
                 String id = new String(customPayloadPacket.data, StandardCharsets.UTF_8);
                 playerEntity.getHeldItem().getData().putString("monster", id);
diff --git a/game/server/src/main/java/net/minecraft/server/world/WorldManager.java b/game/server/src/main/java/net/minecraft/server/world/WorldManager.java
index 545cf873b..a149730de 100644
--- a/game/server/src/main/java/net/minecraft/server/world/WorldManager.java
+++ b/game/server/src/main/java/net/minecraft/server/world/WorldManager.java
@@ -14,6 +14,7 @@ import net.minecraft.core.sound.SoundTypes;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.world.LevelListener;
 import net.minecraft.server.MinecraftServer;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 
 public class WorldManager
@@ -117,7 +118,7 @@ public class WorldManager
     }
 
     @Override
-	public void levelEvent(Player player, int id, int x, int y, int z, int data)
+	public void levelEvent(@Nullable Player player, int id, int x, int y, int z, int data)
     {
         mcServer.playerList.sendPacketToOtherPlayersAroundPoint(player, x, y, z, 64D, worldServer.dimension.id, new PacketPlaySoundEffect(id, x, y, z, data));
     }
diff --git a/game/server/src/main/java/net/minecraft/server/world/WorldServer.java b/game/server/src/main/java/net/minecraft/server/world/WorldServer.java
index d3acec4d6..6356ee414 100644
--- a/game/server/src/main/java/net/minecraft/server/world/WorldServer.java
+++ b/game/server/src/main/java/net/minecraft/server/world/WorldServer.java
@@ -232,7 +232,7 @@ public class WorldServer extends World
         byte b3 = (byte) ((rainbowTicks >>  0) & 0xFF);
 //        System.out.printf("b0:%s b1:%s b2:%s b3:%s\n", b0, b1, b2, b3);
 //        System.out.println("Sent rainbow with " + rainbowTicks + " ticks!");
-        mcServer.playerList.sendPacketToAllPlayersInDimension(new PacketCustomPayload("BTA|RainbowStart", new byte[]{b0, b1, b2, b3}), dimension.id);
+        mcServer.playerList.sendPacketToAllPlayersInDimension(new PacketCustomPayload(PacketCustomPayload.CHANNEL_RAINBOW_START, new byte[]{b0, b1, b2, b3}), dimension.id);
         super.addRainbow(rainbowTicks);
     }
     public ChunkProviderServer chunkProviderServer;
