diff --git a/game/client/setup_bg.sh b/game/client/setup_bg.sh
new file mode 100644
index 000000000..25860dba5
--- /dev/null
+++ b/game/client/setup_bg.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+ROOT_DIR=./src/main/resources/bg
+
+for filename in "${ROOT_DIR}"/*.png; do
+    if ! magick identify "${filename}" | grep "512x256" > /dev/null; then
+        echo "${filename}"
+        magick "${filename}" \
+            -define filter:blur=3 \
+            -define png:compression-level=9 \
+            -define png:format=png24 \
+            -define png:compression-strategy=3 \
+            -filter Lagrange \
+            -resize 512 \
+            -gravity center \
+            -crop 512x256+0+0 \
+            +repage \
+            "${filename}"
+    fi
+done
+
+printf "{\n" > "${ROOT_DIR}"/backgrounds.json
+printf "\t\"replace\": false,\n" >> "${ROOT_DIR}"/backgrounds.json
+printf "\t\"backgrounds\": [\n" >> "${ROOT_DIR}"/backgrounds.json
+for filename in "${ROOT_DIR}"/*.png; do
+    printf "\t\t\"$(basename -s .png "${filename}")\",\n" >> "${ROOT_DIR}"/backgrounds.json
+done
+printf "\t]\n" >> "${ROOT_DIR}"/backgrounds.json
+printf "}\n" >> "${ROOT_DIR}"/backgrounds.json
diff --git a/game/client/src/main/java/net/minecraft/client/Minecraft.java b/game/client/src/main/java/net/minecraft/client/Minecraft.java
index d219fe60f..cf695d47a 100644
--- a/game/client/src/main/java/net/minecraft/client/Minecraft.java
+++ b/game/client/src/main/java/net/minecraft/client/Minecraft.java
@@ -81,6 +81,7 @@ import net.minecraft.client.sound.SoundRepository;
 import org.jetbrains.annotations.Nullable;
 
 import org.lwjgl.LWJGLException;
+import org.lwjgl.glfw.GLFW;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.GL11;
@@ -525,6 +526,7 @@ public class Minecraft
         texturePackList = new TexturePackList(this, mcDataDir);
         textureManager = new TextureManager(this, texturePackList, gameSettings);
 
+        TooltipElement.reloadStyles(texturePackList);
         SoundRepository.initialize(this);
 
         // Show load screen as early as possible
@@ -2283,7 +2285,7 @@ public class Minecraft
         z *= Dimension.getCoordScale(lastDim, newDim);
         thePlayer.moveTo(x, y, z, thePlayer.yRot, thePlayer.xRot);
         ChunkCoordinates newCoordinates = new ChunkCoordinates(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z));
-        if (thePlayer.dimensionEnterCoordinate != null) {
+        if (this.thePlayer.isAlive() && this.thePlayer.dimensionEnterCoordinate != null) {
             double dx = thePlayer.dimensionEnterCoordinate.x - x;
             double dy = thePlayer.dimensionEnterCoordinate.y - y;
             double dz = thePlayer.dimensionEnterCoordinate.z - z;
@@ -2706,7 +2708,7 @@ public class Minecraft
                 }
                 case "--gameDir": {
                     try {
-                        gameDirectory = args[pointer + 1];
+                        minecraftDir = new File(args[pointer + 1]);
                         pointer++;
                     } catch (Exception e) {
                         e.printStackTrace();
@@ -2825,8 +2827,24 @@ public class Minecraft
 
         return INSTANCE != null? (int) (INSTANCE.gameSettings.autosaveTimer.value * 24) * 5 : 0;
     }
-    
+
+    @Override
+    public void copyToClipboard(String str) {
+        GLFW.glfwSetClipboardString(this.gameWindow.getHandle(), str);
+    }
+
+    @Override
+    public String readFromClipboard() {
+        return GLFW.glfwGetClipboardString(this.gameWindow.getHandle());
+    }
+
     public static Minecraft getMinecraft() {
         return INSTANCE;
     }
+
+    static {
+        // This fixes a bug on macOS where the game doesn't start properly.
+        // Mojang does the exact same as of 1.21.4, so this is reasonably legit.
+        System.setProperty("java.awt.headless", "true");
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ExceptionPopupElement.java b/game/client/src/main/java/net/minecraft/client/gui/ExceptionPopupElement.java
index d867b5793..21ffbd4e9 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ExceptionPopupElement.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ExceptionPopupElement.java
@@ -4,8 +4,10 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.popup.PopupScreen;
 import net.minecraft.client.gui.popup.PopupBuilder;
 import net.minecraft.client.gui.popup.PopupCloseListener;
+import net.minecraft.core.Global;
 import net.minecraft.core.net.command.TextFormatting;
 import org.lwjgl.Sys;
+import org.lwjgl.glfw.GLFW;
 import org.lwjgl.opengl.GL11;
 
 import java.awt.*;
@@ -166,18 +168,11 @@ public class ExceptionPopupElement {
                     mc.hasCrashed = false;
                     break;
                 case 1:
-                    Toolkit.getDefaultToolkit()
-                            .getSystemClipboard()
-                            .setContents(
-                                    new StringSelection(message),
-                                    null
-                            );
+                    Global.accessor.copyToClipboard(message);
                     mc.hasCrashed = false;
                     break;
                 case 2:
-                    Toolkit.getDefaultToolkit()
-                            .getSystemClipboard()
-                            .setContents(new StringSelection(message), null);
+                    Global.accessor.copyToClipboard(message);
                     mc.shutdownMinecraftApplet();
                     break;
             }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenPhotoMode.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenPhotoMode.java
index 0b7619178..f0707cedd 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenPhotoMode.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenPhotoMode.java
@@ -2,6 +2,7 @@ package net.minecraft.client.gui;
 
 import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.client.input.controller.ControllerInput;
+import net.minecraft.client.util.helper.FileOpener;
 import net.minecraft.core.Global;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Utils;
@@ -141,7 +142,7 @@ public class ScreenPhotoMode extends Screen
         buttonOpenScreenshotFolder.setActionListener(() -> {
             File f = new File(mc.getMinecraftDir(), "screenshots");
             f.mkdirs();
-            Utils.openDirectory(f);
+            FileOpener.open(f);
         });
 
         buttonCenterScreen = new ButtonElement(10, width - 120, 0, 120, 20, i18n.translateKey("gui.photo_mode.button.center_camera"));
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenSoundTest.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenSoundTest.java
index 64d74e5e5..cda236899 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenSoundTest.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenSoundTest.java
@@ -7,6 +7,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.sound.SoundEngine;
 import net.minecraft.client.sound.SoundEvent;
 import net.minecraft.client.sound.SoundRepository;
+import net.minecraft.client.util.helper.FileOpener;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.Utils;
@@ -95,7 +96,7 @@ public class ScreenSoundTest extends Screen {
 
 
         add(new ListenerButtonElement(30, BUTTON_SPACING, bottom - (BUTTON_SPACING + 20), 20, 20, "")
-            .setActionListener(() -> Utils.openDirectory(new File(mc.getMinecraftDir(), "resources")))
+            .setActionListener(() -> FileOpener.open(new File(mc.getMinecraftDir(), "resources")))
             .setTextures("minecraft:gui/misc/button_folder", "minecraft:gui/misc/button_folder_highlighted", "minecraft:gui/misc/button_folder"));
 
         add(new ListenerButtonElement(31, 20 + BUTTON_SPACING * 2, bottom - (BUTTON_SPACING + 20), 20, 20, "V"))
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenTextureViewer.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenTextureViewer.java
index 13e350144..d266bd799 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenTextureViewer.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenTextureViewer.java
@@ -5,6 +5,7 @@ import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.client.gui.modelviewer.elements.IListenerElement;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.Texture;
+import net.minecraft.client.util.helper.FileOpener;
 import net.minecraft.client.util.helper.Textures;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.helper.Utils;
@@ -90,7 +91,7 @@ public class ScreenTextureViewer extends Screen {
         add(new ListenerButtonElement(12, 40 + BUTTON_SPACING * 3, bottom - BUTTON_SPACING - 20, 20, 20, "D")
             .setActionListener(() -> {
                 Textures.dumpTextures();
-                Utils.openDirectory(new File("dumpTextures"));
+                FileOpener.open(new File("dumpTextures"));
             })
         );
         add(new ListenerButtonElement(13, 60 + BUTTON_SPACING * 4, bottom - BUTTON_SPACING - 20, 20, 20, "T")
diff --git a/game/client/src/main/java/net/minecraft/client/gui/TooltipElement.java b/game/client/src/main/java/net/minecraft/client/gui/TooltipElement.java
index f768851c5..8f77ea0b0 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/TooltipElement.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/TooltipElement.java
@@ -1,25 +1,51 @@
 package net.minecraft.client.gui;
 
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.render.texture.stitcher.IconCoordinate;
+import net.minecraft.client.render.texture.stitcher.TextureRegistry;
+import net.minecraft.client.render.texturepack.TexturePack;
+import net.minecraft.client.render.texturepack.TexturePackList;
 import net.minecraft.core.WeightedRandomBag;
 import net.minecraft.core.data.registry.recipe.entry.RecipeEntryTrommel;
 import net.minecraft.core.data.registry.recipe.RecipeSymbol;
 import net.minecraft.core.item.ItemStack;
-import net.minecraft.client.option.enums.TooltipStyle;
 import net.minecraft.client.render.Font;
-import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.player.inventory.slot.Slot;
 import net.minecraft.core.player.inventory.slot.SlotResult;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.net.command.TextFormatting;
 import net.minecraft.client.gui.guidebook.SlotGuidebook;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.opengl.GL11;
 
 import com.mojang.nbt.tags.CompoundTag;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 public class TooltipElement extends Gui
 {
+    protected final static Logger LOGGER = LogUtils.getLogger();
+    public final static Map<String, Style> styleMap = new HashMap<>();
+    public final static List<String> stylesIdList = new ArrayList<>();
+    protected final static Style defaultStyle = new Style("default", "default", 3, 3, 3, 3);
+
     Minecraft mc;
     Font fr;
 
@@ -57,9 +83,9 @@ public class TooltipElement extends Gui
         x += offsetX;
         y += offsetY;
 
-        int padding = getPadding();
+        final int padding = getPadding();
 
-        drawBackground(x, y, x + width + padding * 2, y + height + padding * 2);
+        drawBackground(x, y, x + width, y + height);
 
 
         for(int i = 0; i < lines.length; i++)
@@ -68,12 +94,7 @@ public class TooltipElement extends Gui
         }
     }
     public int getPadding(){
-        int paddingExtra = 0;
-        if (mc.gameSettings.tooltipStyle.value != TooltipStyle.DEFAULT)
-        {
-            paddingExtra = 1;
-        }
-        return BASE_PADDING + paddingExtra;
+        return BASE_PADDING;
     }
     public int[] drawBackground(int x, int y, int offsetX, int offsetY, int width, int height){
 //        int targetOffset = 0;
@@ -91,126 +112,22 @@ public class TooltipElement extends Gui
         x += offsetX;
         y += offsetY;
 
-        int padding = getPadding();
-
-        return drawBackground(x, y, x + width + padding * 2, y + height + padding * 2);
+        return drawBackground(x, y, x + width, y + height);
     }
 
-    private int[] drawBackground(int minX, int minY, int maxX, int maxY)
+    private int[] drawBackground(final int minX, final int minY, final int maxX, final int maxY)
     {
-        if(mc.gameSettings.tooltipStyle.value == TooltipStyle.MODERN) {
-        	return drawBackgroundModern(minX, minY, maxX, maxY);
-        }
-        
-        int topLeftCornerX = minX;
-        int topLeftCornerY = minY;
-        int bottomLeftCornerX = minX;
-        int bottomLeftCornerY = maxY - 7;
-        int topRightCornerX = maxX - 7;
-        int topRightCornerY = minY;
-        int bottomRightCornerX = maxX - 7;
-        int bottomRightCornerY = maxY - 7;
-        int horWidth = (maxX - minX) - 14;
-        int vertHeight = (maxY - minY) - 14;
-        int horWidth2 = (maxX - minX) - 6;
-        int vertHeight2 = (maxY - minY) - 6;
-
-        Tessellator tl = Tessellator.instance;
-
-        mc.textureManager.bindTexture(mc.textureManager.loadTexture(mc.gameSettings.tooltipStyle.value.getFilePath()));
-
-        GL11.glEnable(GL11.GL_BLEND);
-        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-
-        tl.startDrawingQuads();
-
-        // Draw corners
-        // Top left
-        tl.drawRectangleWithUV(topLeftCornerX,      topLeftCornerY,     7, 7, 0 / 32F, 0 / 32F, 7 / 32F, 7 / 32F);
-        // Bottom left
-        tl.drawRectangleWithUV(bottomLeftCornerX,   bottomLeftCornerY,  7, 7, 0 / 32F, 7 / 32F, 7 / 32F, 7 / 32F);
-        // Top right
-        tl.drawRectangleWithUV(topRightCornerX,     topRightCornerY,    7, 7, 7 / 32F, 0 / 32F, 7 / 32F, 7 / 32F);
-        // Bottom right
-        tl.drawRectangleWithUV(bottomRightCornerX,  bottomRightCornerY, 7, 7, 7 / 32F, 7 / 32F, 7 / 32F, 7 / 32F);
-
-        // Draw top
-        for (int x = minX + 7; x < minX + 7 + (horWidth / 11) * 11; x += 11)
-        {
-            tl.drawRectangleWithUV(x, minY, 11, 3, 14 / 32F, 0 / 32F, 11 / 32F, 3 / 32F);
-        }
-        int finalWidth = horWidth - ((horWidth / 11) * 11);
-        tl.drawRectangleWithUV(topRightCornerX - finalWidth, minY, finalWidth, 3, 14 / 32F, 0 / 32F, finalWidth / 32F, 3 / 32F);
+        final Style style = styleMap.getOrDefault(this.mc.gameSettings.tooltipStyle.value, defaultStyle);
+        if (style != null) {
+            GL11.glEnable(GL11.GL_BLEND);
+            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
 
-        // Draw bottom
-        for (int x = minX + 7; x < minX + 7 + (horWidth / 11) * 11; x += 11)
-        {
-            tl.drawRectangleWithUV(x, maxY - 3, 11, 3, 14 / 32F, 11 / 32F, 11 / 32F, 3 / 32F);
-        }
-        tl.drawRectangleWithUV(bottomRightCornerX - finalWidth, maxY - 3, finalWidth, 3, 14 / 32F, 11 / 32F, finalWidth / 32F, 3 / 32F);
+            drawGuiIcon(minX, minY, maxX - minX + BASE_PADDING * 2, maxY - minY + BASE_PADDING * 2, style.getInnerIcon());
+            drawGuiIcon(minX - style.paddingLeft, minY - style.paddingTop, maxX - minX + BASE_PADDING * 2 + style.paddingLeft + style.paddingRight, maxY - minY + BASE_PADDING * 2 + style.paddingTop + style.paddingBottom, style.getBorderIcon());
 
-        // Draw left
-        for (int y = minY + 7; y < minY + 7 + (vertHeight / 11) * 11; y += 11)
-        {
-            tl.drawRectangleWithUV(minX, y, 3, 11, 0 / 32F, 14 / 32F, 3 / 32F, 11 / 32F);
+            GL11.glDisable(GL11.GL_BLEND);
         }
-        int finalHeight = vertHeight - ((vertHeight / 11) * 11);
-        tl.drawRectangleWithUV(minX, bottomLeftCornerY - finalHeight, 3, finalHeight, 0 / 32F, 14 / 32F, 3 / 32F, finalHeight / 32F);
-
-        // Draw right
-        for (int y = minY + 7; y < minY + 7 + (vertHeight / 11) * 11; y += 11)
-        {
-            tl.drawRectangleWithUV(maxX - 3, y, 3, 11, 11 / 32F, 14 / 32F, 3 / 32F, 11 / 32F);
-        }
-        tl.drawRectangleWithUV(maxX - 3, bottomRightCornerY - finalHeight, 3, finalHeight, 11 / 32F, 14 / 32F, 3 / 32F, finalHeight / 32F);
-
-        // Draw background
-        for (int x = minX + 3; x < minX + 3 + (horWidth2 / 8) * 8; x += 8)
-        {
-            for (int y = minY + 3; y < minY + 3 + (vertHeight2 / 8) * 8; y += 8)
-            {
-                tl.drawRectangleWithUV(x, y, 8, 8, 14 / 32F, 14 / 32F, 8 / 32F, 8 / 32F);
-            }
-        }
-        int finalHeight2 = vertHeight2 - ((vertHeight2 / 8) * 8);
-        int finalWidth2 = horWidth2 - ((horWidth2 / 8) * 8);
-        for (int x = minX + 3; x < minX + 3 + (horWidth2 / 8) * 8; x += 8)
-        {
-            tl.drawRectangleWithUV(x, maxY - 3 - finalHeight2, 8, finalHeight2, 14 / 32F, 14 / 32F, 8 / 32F, finalHeight2 / 32F);
-        }
-        for (int y = minY + 3; y < minY + 3  + (vertHeight2 / 8) * 8; y += 8)
-        {
-            tl.drawRectangleWithUV(maxX - 3 - finalWidth2, y, finalWidth2, 8, 14 / 32F, 14 / 32F, finalWidth2 / 32F, 8 / 32F);
-        }
-        tl.drawRectangleWithUV(maxX - 3 - finalWidth2, maxY - 3 - finalHeight2, finalWidth2, finalHeight2, 14 / 32F, 14 / 32F, finalWidth / 32F, finalWidth2 / 32F);
-
-        tl.draw();
-
-        GL11.glDisable(GL11.GL_BLEND);
-        return new int[]{topLeftCornerX, topLeftCornerY};
-    }
-    
-    private int[] drawBackgroundModern(int minX, int minY, int maxX, int maxY) {
-    	int x = minX + 4;
-    	int y = minY + 4;
-    	int width = maxX - minX - 8;
-    	int height = maxY - minY - 8;
-    	
-		int bgColor = 0xf0100010;
-		int lineColorTop = 0x505000ff;
-		int lineColorBottom = (lineColorTop & 0xfefefe) >> 1 | lineColorTop & 0xff000000;
-    	
-    	drawGradientRect(x - 3, y - 4, x + width + 3, y - 3, bgColor, bgColor);
-		drawGradientRect(x - 3, y + height + 3, x + width + 3, y + height + 4, bgColor, bgColor);
-		drawGradientRect(x - 3, y - 3, x + width + 3, y + height + 3, bgColor, bgColor);
-		drawGradientRect(x - 4, y - 3, x - 3, y + height + 3, bgColor, bgColor);
-		drawGradientRect(x + width + 3, y - 3, x + width + 4, y + height + 3, bgColor, bgColor);
-		
-		drawGradientRect(x - 3, (y - 3) + 1, (x - 3) + 1, (y + height + 3) - 1, lineColorTop, lineColorBottom);
-		drawGradientRect(x + width + 2, (y - 3) + 1, x + width + 3, (y + height + 3) - 1, lineColorTop, lineColorBottom);
-		drawGradientRect(x - 3, y - 3, x + width + 3, (y - 3) + 1, lineColorTop, lineColorTop);
-		drawGradientRect(x - 3, y + height + 2, x + width + 3, y + height + 3, lineColorBottom, lineColorBottom);
-        return new int[]{x - 3, y - 4};
+        return new int[]{minX, minY};
     }
 
 	public String getTooltipText(ItemStack itemStack, boolean showDescription, Slot slot) {
@@ -251,9 +168,9 @@ public class TooltipElement extends Gui
                 if(((SlotGuidebook) slot).recipe != null) {
                     if (((SlotGuidebook) slot).recipe instanceof RecipeEntryTrommel) {
                         RecipeSymbol input = (RecipeSymbol) ((SlotGuidebook) slot).recipe.getInput();
-                        if(!input.matches(slot.getItem())){
+                        if(!input.matches(slot.getItemStack())){
                             WeightedRandomBag<?> bag = (WeightedRandomBag<?>) ((SlotGuidebook) slot).recipe.getOutput();
-                            double percent = bag.getAsPercentage(slot.getItem());
+                            double percent = bag.getAsPercentage(slot.getItemStack());
                             text.append('\n').append(TextFormatting.LIGHT_GRAY).append(String.format("%.2f", percent)).append("%");
                         }
                     }
@@ -351,4 +268,112 @@ public class TooltipElement extends Gui
         return string.toString();
     }
 
+    public static void reloadStyles(final @NotNull TexturePackList packList) {
+        styleMap.clear();
+        stylesIdList.clear();
+
+
+        final Collection<String> styleIds = new ArrayList<>();
+        for (int i = packList.selectedPacks.size() - 1; i >= 0; i--) {
+            final TexturePack pack = packList.selectedPacks.get(i);
+            try (final InputStream stylesStream = pack.getResourceAsStream("/assets/minecraft/textures/gui/sprites/tooltip/styles.json")) {
+                if (stylesStream != null) {
+                    final JsonObject stylesListObject = JsonParser.parseReader(new InputStreamReader(stylesStream)).getAsJsonObject();
+                    final boolean replace = stylesListObject.has("replace") ? stylesListObject.get("replace").getAsBoolean() : false;
+                    if (replace) styleIds.clear();
+                    final JsonArray styles = stylesListObject.getAsJsonArray("styles");
+                    for (final JsonElement element : styles) {
+                        final String styleId = element.getAsString();
+                        if (!styleIds.contains(styleId)) {
+                            styleIds.add(styleId);
+                        }
+                    }
+                }
+            } catch (final IOException ioException) {
+                LOGGER.error("Failed to load styles data!", ioException);
+            } catch (final RuntimeException runtimeException) {
+                LOGGER.error("Error occurred while parsing 'styles.json'!", runtimeException);
+            }
+        }
+        styleIds.add("default");
+
+        for (final String styleId : styleIds) {
+            JsonObject properties = null;
+            try (final InputStream propertiesStream = packList.getResourceAsStream("/assets/minecraft/textures/gui/sprites/tooltip/" + styleId + "/properties.json")) {
+                if (propertiesStream != null) {
+                    properties = JsonParser.parseReader(new JsonReader(new InputStreamReader(propertiesStream))).getAsJsonObject();
+                }
+            } catch (final IOException ioException) {
+                LOGGER.error("Failed to load style '{}' properties json!", styleId, ioException);
+            } catch (final RuntimeException runtimeException) {
+                LOGGER.error("Error occurred while parsing '{}/properties.json'!", styleId, runtimeException);
+            }
+            final Style style;
+            if (properties == null) {
+                style = new Style(styleId, String.format("options.tooltipStyle.%s", styleId), 3, 3, 3, 3);
+            } else {
+                final String key = properties.has("key") ? properties.get("key").getAsString() : String.format("options.tooltipStyle.%s", styleId);
+                final int top;
+                final int bottom;
+                final int left;
+                final int right;
+                if (properties.has("padding")) {
+                    final JsonElement padding = properties.get("padding");
+                    if (padding.isJsonPrimitive()) {
+                        top = bottom = left = right = padding.getAsInt();
+                    } else {
+                        final JsonObject paddingObject = padding.getAsJsonObject();
+                        top = paddingObject.has("top") ? paddingObject.get("top").getAsInt() : 3;
+                        bottom = paddingObject.has("bottom") ? paddingObject.get("bottom").getAsInt() : 3;
+                        left = paddingObject.has("left") ? paddingObject.get("left").getAsInt() : 3;
+                        right = paddingObject.has("right") ? paddingObject.get("right").getAsInt() : 3;
+                    }
+                } else {
+                    top = bottom = left = right = 3;
+                }
+                style = new Style(styleId, key, top, bottom, left, right);
+            }
+            styleMap.put(styleId, style);
+            stylesIdList.add(styleId);
+        }
+        if (!styleMap.containsKey("default")) {
+            styleMap.put("default", defaultStyle);
+            stylesIdList.add("default");
+        }
+        if (Minecraft.getMinecraft().gameSettings.tooltipStyle.getValueIndex() == -1) {
+            Minecraft.getMinecraft().gameSettings.tooltipStyle.set("default");
+        }
+    }
+
+    public static class Style {
+        public final String id;
+        public final String translationKey;
+        public final int paddingTop;
+        public final int paddingBottom;
+        public final int paddingLeft;
+        public final int paddingRight;
+
+        private final IconCoordinate innerIcon;
+        private final IconCoordinate borderIcon;
+
+        public Style(final String id, final String translationKey, final int paddingTop, final int paddingBottom, final int paddingLeft, final int paddingRight) {
+            this.id = id;
+            this.translationKey = translationKey;
+            this.paddingTop = paddingTop;
+            this.paddingBottom = paddingBottom;
+            this.paddingLeft = paddingLeft;
+            this.paddingRight = paddingRight;
+
+            this.innerIcon = TextureRegistry.getTexture("minecraft:gui/tooltip/" + id + "/inner");
+            this.borderIcon = TextureRegistry.getTexture("minecraft:gui/tooltip/" + id + "/border");
+        }
+
+        public IconCoordinate getInnerIcon() {
+            return this.innerIcon;
+        }
+
+        public IconCoordinate getBorderIcon() {
+            return this.borderIcon;
+        }
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/chat/GuiElementChatSuggestions.java b/game/client/src/main/java/net/minecraft/client/gui/chat/GuiElementChatSuggestions.java
index 53731bc4c..fa1b9f38d 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/chat/GuiElementChatSuggestions.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/chat/GuiElementChatSuggestions.java
@@ -198,17 +198,14 @@ public class GuiElementChatSuggestions extends Gui {
         return commandUsage;
     }
 
-    public void keyTyped(char c, int key) {
-        int mouseX = getScaledMouseX(this.mc);
-        int mouseY = getScaledMouseY(this.mc) - 1;
-
-        int TAB = 15;
-        int LEFT_SHIFT = 42;
+    public void keyTyped(final char c, final int key) {
+        final int mouseX = getScaledMouseX(this.mc);
+        final int mouseY = getScaledMouseY(this.mc) - 1;
 
-        if (key == TAB) {
+        if (key == Keyboard.KEY_TAB) {
             if (this.commandIndex == -1 && this.isHoveringOverSuggestions(mouseX, mouseY)) {
                 this.cycleToSuggestion(this.getIndexOfSuggestionBeingHoveredOver(mouseX, mouseY).get());
-            } else if (Keyboard.isKeyDown(LEFT_SHIFT)) {
+            } else if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
                 this.cycleThroughSuggestions(-1);
             } else {
                 this.cycleThroughSuggestions();
@@ -251,15 +248,15 @@ public class GuiElementChatSuggestions extends Gui {
         }
     }
 
-    private boolean shouldApplySuggestion(char c, int key) {
+    private boolean shouldApplySuggestion(final char c, final int key) {
         return this.textField.isCharacterAllowed(c)
-            || ((key == 46 || key == 47) && (Keyboard.isKeyDown(29) || Keyboard.isKeyDown(157)))
-            || key == 199
-            || key == 207
-            || key == 203
-            || key == 205
-            || key == 14
-            || key == 211;
+            || ((key == Keyboard.KEY_C || key == Keyboard.KEY_V) && (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)))
+            || key == Keyboard.KEY_HOME
+            || key == Keyboard.KEY_END
+            || key == Keyboard.KEY_LEFT
+            || key == Keyboard.KEY_RIGHT
+            || key == Keyboard.KEY_BACK
+            || key == Keyboard.KEY_DELETE;
     }
 
     private void finishUpdatingSuggestions() {
@@ -400,7 +397,7 @@ public class GuiElementChatSuggestions extends Gui {
             return serverSuggestions.get(CommandManagerPacketKeys.SUGGESTION_CONTEXT_START_POS).getAsInt();
         }
         try {
-            return this.parseResults != null ? this.parseResults.getContext().findSuggestionContext(this.tablessCursor).startPos : 0;
+            return this.parseResults != null ? this.parseResults.getContext().findSuggestionContext(Math.max(this.tablessCursor, 1)).startPos : 0; // TODO possibly investigate why tabless cursor needs to be bound to [1, inf)
         } catch (IllegalStateException e) {
             LOGGER.error("", e);
             return 0;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
index 823ab8f48..9901455d8 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
@@ -79,7 +79,7 @@ public abstract class ScreenContainerAbstract extends Screen
 			final Slot slot1 = inventorySlots.slots.get(i);
 			boolean mouseOver = getIsMouseOverSlot(slot1, mx, my);
 			if(!itemDragHandler.isSlotDragged(slot1)) {
-				itemElement.render(slot1.getItem(), slot1.x, slot1.y, mouseOver, slot1);
+				itemElement.render(slot1.getItemStack(), slot1.x, slot1.y, mouseOver, slot1);
 			}
 			if (mouseOver)
 			{
@@ -113,7 +113,7 @@ public abstract class ScreenContainerAbstract extends Screen
 		if (inventoryplayer.getHeldItemStack() == null && slot != null && slot.hasItem())
 		{
 			boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-			String str = tooltipElement.getTooltipText(slot.getItem(), showDescription, slot);
+			String str = tooltipElement.getTooltipText(slot.getItemStack(), showDescription, slot);
 			if(str.length() > 0)
 			{
 				tooltipElement.render(str, mx, my, 8, -8);
@@ -164,7 +164,7 @@ public abstract class ScreenContainerAbstract extends Screen
 			if(mc.gameSettings.keyShowRecipe.isKeyboardKey(eventKey)){
 				Slot slot = inventorySlots.slots.get(slotId);
 				if(slot.hasItem()){
-					String query = "r:"+slot.getItem().getDisplayName()+"!";
+					String query = "r:"+slot.getItemStack().getDisplayName()+"!";
 //					removed();
 //					mc.thePlayer.closeScreen();
 					GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
@@ -185,7 +185,7 @@ public abstract class ScreenContainerAbstract extends Screen
 			if(mc.gameSettings.keyShowUsage.isKeyboardKey(eventKey)){
 				Slot slot = inventorySlots.slots.get(slotId);
 				if(slot.hasItem()) {
-					String query = "u:" + slot.getItem().getDisplayName() + "!";
+					String query = "u:" + slot.getItemStack().getDisplayName() + "!";
 //					removed();
 //					mc.thePlayer.closeScreen();
 					GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
@@ -292,7 +292,7 @@ public abstract class ScreenContainerAbstract extends Screen
 			// Duplicate items with middle mouse button
 			if(mouseButton == 2) {
 				Slot slot = inventorySlots.getSlot(slotId);
-				if (slot.getItem() == null) {
+				if (slot.getItemStack() == null) {
 					mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.SORT, new int[] {slotId, 64}, mc.thePlayer);
 				} else {
 					mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, new int[] {slotId, 64}, mc.thePlayer);
@@ -325,7 +325,7 @@ public abstract class ScreenContainerAbstract extends Screen
 		int target = 0; 
 
 		Slot slot = inventorySlots.getSlot(slotId);
-		ItemStack stackInSlot = slot != null ? slot.getItem() : null;
+		ItemStack stackInSlot = slot != null ? slot.getItemStack() : null;
 		Item itemInSlot = stackInSlot != null ? stackInSlot.getItem() : null;
 		int clickedItemId = stackInSlot != null ? stackInSlot.getItem().id : 0;
 		ItemStack grabbedItem = mc.thePlayer.inventory.getHeldItemStack();
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/SlotGuidebook.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/SlotGuidebook.java
index 6539c502f..279951503 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/SlotGuidebook.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/SlotGuidebook.java
@@ -12,6 +12,7 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.gamemode.Gamemode;
 import net.minecraft.core.player.inventory.slot.Slot;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 import java.util.Random;
@@ -63,7 +64,7 @@ public class SlotGuidebook extends Slot
 	}
 
 	@Override
-	public ItemStack remove(final int i)
+	public @Nullable ItemStack remove(final int i)
 	{
 		return null;
 	}
@@ -81,7 +82,7 @@ public class SlotGuidebook extends Slot
 	}
 
 	@Override
-	public ItemStack getItem()
+	public @Nullable ItemStack getItemStack()
 	{
 		return item;
 	}
@@ -97,7 +98,7 @@ public class SlotGuidebook extends Slot
     }
 
 	@Override
-	public void set(final ItemStack itemstack)
+	public void set(final @Nullable ItemStack itemstack)
 	{
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/RecipePageCrafting.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/RecipePageCrafting.java
index fd6f3d365..5e18d1e48 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/RecipePageCrafting.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/crafting/RecipePageCrafting.java
@@ -123,7 +123,7 @@ public class RecipePageCrafting
             }
             drawSlot(x+slot.x -1,y+slot.y -1,0xFFFFFFFF);
             if(getIsMouseOverSlot(slot,x,y,mouseX,mouseY)) mouseOverSlot = slot;
-            itemElement.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
+            itemElement.render(slot.getItemStack(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
         }
     }
 
@@ -142,7 +142,7 @@ public class RecipePageCrafting
             }
             if(hoveringSlot != null){
                 if(hoveringSlot.hasItem()){
-                    String query = "r:"+hoveringSlot.getItem().getDisplayName()+"!";
+                    String query = "r:"+hoveringSlot.getItemStack().getDisplayName()+"!";
                     GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
                     GuidebookPageSearch.searchField.setText(query);
                     ScreenGuidebook.getPageManager().updatePages();
@@ -157,7 +157,7 @@ public class RecipePageCrafting
             }
             if(hoveringSlot != null) {
                 if (hoveringSlot.hasItem()) {
-                    String query = "u:" + hoveringSlot.getItem().getDisplayName() + "!";
+                    String query = "u:" + hoveringSlot.getItemStack().getDisplayName() + "!";
                     GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
                     GuidebookPageSearch.searchField.setText(query);
                     ScreenGuidebook.getPageManager().updatePages();
@@ -196,7 +196,7 @@ public class RecipePageCrafting
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItemStack(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
                     tooltipElement.render(str, mouseX, mouseY, 8, -8);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java
index 8cbb7736f..1e8f99785 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java
@@ -188,7 +188,7 @@ public class GuidebookPageMob
                         drawSlot(x + 7 + (i % 7) * 21, yOffset + (i / 7) * 20, 0xFFFFFFFF);
                         GL11.glPushMatrix();
                         GL11.glTranslatef(0, 0, 50f);
-                        itemElement.render(slot.getItem(), x + 8 + (i % 7) * 21, yOffset + 1 + (i / 7) * 20, mouseOver, slot);
+                        itemElement.render(slot.getItemStack(), x + 8 + (i % 7) * 21, yOffset + 1 + (i / 7) * 20, mouseOver, slot);
                         GL11.glPopMatrix();
                         if (slot.getIsDiscovered(mc.thePlayer)) {
                             String amountString = drop.getMinAmount() == drop.getMaxAmount() ? String.valueOf(drop.getMinAmount()) : drop.getMinAmount() + "-" + drop.getMaxAmount();
@@ -278,7 +278,7 @@ public class GuidebookPageMob
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItemStack(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
                     tooltipElement.render(str, mouseX, mouseY, 8, -8);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageBlastSmelting.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageBlastSmelting.java
index 7977210aa..53acf5caa 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageBlastSmelting.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageBlastSmelting.java
@@ -78,7 +78,7 @@ public class RecipePageBlastSmelting
         for (SlotGuidebook slot : slots) {
             drawSlot(x+slot.x -1,y+slot.y -1,0xFFFFFFFF);
             if(getIsMouseOverSlot(slot,x,y,mouseX,mouseY)) mouseOverSlot = slot;
-            itemElement.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
+            itemElement.render(slot.getItemStack(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
         }
     }
 
@@ -97,7 +97,7 @@ public class RecipePageBlastSmelting
             }
             if(hoveringSlot != null){
                 if(hoveringSlot.hasItem()){
-                    String query = "r:"+hoveringSlot.getItem().getDisplayName()+"!";
+                    String query = "r:"+hoveringSlot.getItemStack().getDisplayName()+"!";
                     GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
                     GuidebookPageSearch.searchField.setText(query);
                     ScreenGuidebook.getPageManager().updatePages();
@@ -112,7 +112,7 @@ public class RecipePageBlastSmelting
             }
             if(hoveringSlot != null) {
                 if (hoveringSlot.hasItem()) {
-                    String query = "u:" + hoveringSlot.getItem().getDisplayName() + "!";
+                    String query = "u:" + hoveringSlot.getItemStack().getDisplayName() + "!";
                     GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
                     GuidebookPageSearch.searchField.setText(query);
                     ScreenGuidebook.getPageManager().updatePages();
@@ -151,7 +151,7 @@ public class RecipePageBlastSmelting
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItemStack(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
                     tooltipElement.render(str, mouseX, mouseY, 8, -8);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageSmelting.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageSmelting.java
index 763d2cb1f..87143126e 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageSmelting.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/smelting/RecipePageSmelting.java
@@ -78,7 +78,7 @@ public class RecipePageSmelting
         for (SlotGuidebook slot : slots) {
             drawSlot(x+slot.x -1,y+slot.y -1,0xFFFFFFFF);
             if(getIsMouseOverSlot(slot,x,y,mouseX,mouseY)) mouseOverSlot = slot;
-            itemElement.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
+            itemElement.render(slot.getItemStack(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
         }
     }
 
@@ -97,7 +97,7 @@ public class RecipePageSmelting
             }
             if(hoveringSlot != null){
                 if(hoveringSlot.hasItem()){
-                    String query = "r:"+hoveringSlot.getItem().getDisplayName()+"!";
+                    String query = "r:"+hoveringSlot.getItemStack().getDisplayName()+"!";
                     GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
                     GuidebookPageSearch.searchField.setText(query);
                     ScreenGuidebook.getPageManager().updatePages();
@@ -112,7 +112,7 @@ public class RecipePageSmelting
             }
             if(hoveringSlot != null) {
                 if (hoveringSlot.hasItem()) {
-                    String query = "u:" + hoveringSlot.getItem().getDisplayName() + "!";
+                    String query = "u:" + hoveringSlot.getItemStack().getDisplayName() + "!";
                     GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
                     GuidebookPageSearch.searchField.setText(query);
                     ScreenGuidebook.getPageManager().updatePages();
@@ -151,7 +151,7 @@ public class RecipePageSmelting
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItemStack(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
                     tooltipElement.render(str, mouseX, mouseY, 8, -8);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/trommeling/RecipePageTrommel.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/trommeling/RecipePageTrommel.java
index e5548159b..2175f4d93 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/trommeling/RecipePageTrommel.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/trommeling/RecipePageTrommel.java
@@ -96,7 +96,7 @@ public class RecipePageTrommel
             for (SlotGuidebook slot : slots) {
                 if (slot.recipe instanceof RecipeEntryTrommel) {
                     RecipeSymbol input = (RecipeSymbol) slot.recipe.getInput();
-                    if (!input.matches(slot.getItem())) {
+                    if (!input.matches(slot.getItemStack())) {
                         if(slot.recipeAmount > 8){
                             int recipeIndexMax = Math.round((float) slot.recipeAmount /9);
                             if(slot.recipeIndex >= recipeIndexMax){
@@ -127,7 +127,7 @@ public class RecipePageTrommel
         for (SlotGuidebook slot : slots) {
             drawSlot(x+slot.x -1,y+slot.y -1,0xFFFFFFFF);
             if(getIsMouseOverSlot(slot,x,y,mouseX,mouseY)) mouseOverSlot = slot;
-            itemElement.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
+            itemElement.render(slot.getItemStack(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
         }
     }
 
@@ -146,7 +146,7 @@ public class RecipePageTrommel
             }
             if(hoveringSlot != null){
                 if(hoveringSlot.hasItem()){
-                    String query = "r:"+hoveringSlot.getItem().getDisplayName()+"!";
+                    String query = "r:"+hoveringSlot.getItemStack().getDisplayName()+"!";
                     GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
                     GuidebookPageSearch.searchField.setText(query);
                     ScreenGuidebook.getPageManager().updatePages();
@@ -161,7 +161,7 @@ public class RecipePageTrommel
             }
             if(hoveringSlot != null) {
                 if (hoveringSlot.hasItem()) {
-                    String query = "u:" + hoveringSlot.getItem().getDisplayName() + "!";
+                    String query = "u:" + hoveringSlot.getItemStack().getDisplayName() + "!";
                     GuidebookPageManager.searchQuery = SearchQuery.resolve(query);
                     GuidebookPageSearch.searchField.setText(query);
                     ScreenGuidebook.getPageManager().updatePages();
@@ -200,7 +200,7 @@ public class RecipePageTrommel
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItemStack(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
                     tooltipElement.render(str, mouseX, mouseY, 8, -8);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
index 855f530a5..5ce0c784d 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
@@ -21,6 +21,7 @@ import net.minecraft.client.render.shader.Shaders;
 import net.minecraft.client.render.shader.ShadersRenderer;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.Texture;
+import net.minecraft.client.util.helper.FileOpener;
 import net.minecraft.client.util.helper.Textures;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntity;
@@ -142,7 +143,7 @@ public class ScreenModelViewer extends ScreenPhotoMode implements ListenerTextFi
         buttonReloadTextures.setActionListener(() -> mc.textureManager.refreshTexturesAndDisplayErrors());
         buttonOpenScreenshotFolder = (ListenerButtonElement) new ListenerButtonElement(30, buttonReloadTextures.getWidth() + buttonReloadTextures.getX() + 1, buttonReloadTextures.getY(), 20, 20, "")
             .setTextures("minecraft:gui/misc/button_folder", "minecraft:gui/misc/button_folder_highlighted", "minecraft:gui/misc/button_folder");
-        buttonOpenScreenshotFolder.setActionListener(() -> Utils.openDirectory(new File(mc.getMinecraftDir(), "")));
+        buttonOpenScreenshotFolder.setActionListener(() -> FileOpener.open(new File(mc.getMinecraftDir(), "")));
 
         buttonCenterScreen = new ListenerButtonElement(10, 0, 0, 120, 20, i18n.translateKey("gui.photo_mode.button.center_camera"));
         buttonCenterScreen.setActionListener(() -> {
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 f7626ed11..0aba78c6e 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
@@ -8,8 +8,8 @@ import net.minecraft.client.render.window.CursorShape;
 public class FloatOptionComponent
         extends ButtonComponent
 {
-    private final OptionFloat option;
-    private final SliderElement slider;
+    protected final OptionFloat option;
+    protected final SliderElement slider;
 
     public FloatOptionComponent(OptionFloat option)
     {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/TooltipPickerComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/TooltipPickerComponent.java
index fd86d799c..2aa7d2655 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/TooltipPickerComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/TooltipPickerComponent.java
@@ -1,34 +1,28 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.gui.TooltipElement;
-import net.minecraft.client.option.OptionToggleable;
-import net.minecraft.client.option.enums.TooltipStyle;
+import net.minecraft.client.option.OptionTooltip;
 import net.minecraft.client.render.window.CursorShape;
 import org.lwjgl.opengl.GL11;
 
-public class TooltipPickerComponent<E>
-    extends ToggleableOptionComponent<E> {
+public class TooltipPickerComponent
+    extends ToggleableOptionComponent<String> {
 
     private final TooltipElement tooltip;
 
-    public TooltipPickerComponent(OptionToggleable<E> option) {
+    public TooltipPickerComponent(final OptionTooltip option) {
         super(option);
 
         this.tooltip = new TooltipElement(mc);
     }
 
     @Override
-    protected void renderButton(int x, int y, int relativeButtonX, int relativeButtonY, int buttonWidth, int buttonHeight, int relativeMouseX, int relativeMouseY) {
+    protected void renderButton(final int x, final int y, final int relativeButtonX, final int relativeButtonY, final int buttonWidth, final int buttonHeight, final int relativeMouseX, final int relativeMouseY) {
         super.renderButton(x, y, relativeButtonX, relativeButtonY, buttonWidth, buttonHeight, relativeMouseX, relativeMouseY);
 
-        int stringWidth = mc.font.getStringWidth(this.option.getDisplayStringValue());
-        int padding = 3;
-        int yOffset = 0;
-        if (this.option.value != TooltipStyle.DEFAULT) {
-            padding++;
-            yOffset = -1;
-        }
-        stringWidth += padding * 2;
+        final int padding = 3;
+        final int yOffset = 0;
+        final int stringWidth = mc.font.getStringWidth(this.option.getDisplayStringValue()) + padding * 2;
         GL11.glColor4f(1, 1, 1, 1);
         this.tooltip.render(this.option.getDisplayStringValue(), x + relativeButtonX + buttonWidth / 2 - stringWidth / 2, y + relativeButtonY + 3 + yOffset, 0, 0);
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java b/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
index 0a474d34d..c2392c95d 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
@@ -10,8 +10,10 @@ import net.minecraft.client.gui.ScreenTextureViewer;
 import net.minecraft.client.gui.achievements.ScreenAchievements;
 import net.minecraft.client.gui.modelviewer.ScreenModelViewer;
 import net.minecraft.client.gui.options.components.*;
+import net.minecraft.client.option.enums.LightmapStyle;
 import net.minecraft.client.player.controller.PlayerControllerSP;
 import net.minecraft.client.sound.SoundEngine;
+import net.minecraft.client.util.helper.FileOpener;
 import net.minecraft.client.world.WorldClient;
 import net.minecraft.core.Global;
 import net.minecraft.core.achievement.stat.Stat;
@@ -66,7 +68,7 @@ public abstract class OptionsPages
                 .withComponent(new ShortcutComponent("gui.options.page.general.button.edit_hud", () -> mc.displayScreen(new ScreenHudDesigner(mc.currentScreen))))
                 .withComponent(new IntegerOptionComponent(mc.gameSettings.guiScale))
                 .withComponent(new FloatOptionComponent(mc.gameSettings.screenPadding))
-                .withComponent(new TooltipPickerComponent<>(mc.gameSettings.tooltipStyle))
+                .withComponent(new TooltipPickerComponent(mc.gameSettings.tooltipStyle))
                 .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.chatVisibility))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.fpsInOverlay))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.versionInOverlay))
@@ -84,12 +86,12 @@ public abstract class OptionsPages
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.forceUnicodeFont))
                 .withComponent(new FloatOptionComponent(mc.gameSettings.autosaveTimer))
             )
-            .withComponent(new ShortcutComponent("gui.options.page.general.button.open_worlds_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "saves"))))
+            .withComponent(new ShortcutComponent("gui.options.page.general.button.open_worlds_folder", () -> FileOpener.open(new File(mc.getMinecraftDir(), "saves"))))
             .withComponent(new ShortcutComponent("gui.options.page.general.button.open_screenshots_folder", () -> {
                 final File f = new File(mc.getMinecraftDir(), "screenshots");
                 //noinspection ResultOfMethodCallIgnored
                 f.mkdirs();
-                Utils.openDirectory(f);
+                FileOpener.open(f);
             }))
         );
 
@@ -148,7 +150,13 @@ public abstract class OptionsPages
             )
             .withComponent(new OptionsCategory("gui.options.page.video.category.visuals")
                 .withComponent(Minecraft.GPU_VENDOR == EnumGPUVendor.INTEL ? null : lightmapComponent)
-                .withComponent(new FloatOptionComponent(mc.gameSettings.brightness))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.brightness){
+                    @Override
+                    public void render(final int x, final int y, final int width, final int relativeMouseX, final int relativeMouseY) {
+                        this.slider.enabled = mc.gameSettings.lightmapStyle.value != LightmapStyle.DISABLED;
+                        super.render(x, y, width, relativeMouseX, relativeMouseY);
+                    }
+                })
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.fovModification))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.screenMotionEffects))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.fog))
@@ -269,7 +277,7 @@ public abstract class OptionsPages
         );
 
         TEXTURE_PACKS = register(new OptionsPage("gui.options.page.texture_packs.title", new ItemStack(Items.PAINTING))
-            .withComponent(new ShortcutComponent("gui.options.page.texture_packs.button.open_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "texturepacks"))))
+            .withComponent(new ShortcutComponent("gui.options.page.texture_packs.button.open_folder", () -> FileOpener.open(new File(mc.getMinecraftDir(), "texturepacks"))))
             .withComponent(new OptionsCategory("gui.options.page.texture_packs.category.textures")
                 .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.animations))
                 .withComponent(new BooleanOptionComponent(mc.gameSettings.customAnimations))
@@ -286,7 +294,7 @@ public abstract class OptionsPages
             )
         );
         LANGUAGE = register(new OptionsPage("gui.options.page.language_packs.title", new ItemStack(Items.BOOK))
-            .withComponent(new ShortcutComponent("gui.options.page.language_packs.button.open_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "languages"))))
+            .withComponent(new ShortcutComponent("gui.options.page.language_packs.button.open_folder", () -> FileOpener.open(new File(mc.getMinecraftDir(), "languages"))))
             .withComponent(new OptionsCategory("gui.options.page.language_packs.category.language_packs")
                 .withComponent(new LanguagePackListComponent())
             )
@@ -353,7 +361,7 @@ public abstract class OptionsPages
                 }))
                 .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.datadumper", () ->{
                     DataDumper.main(new String[0]);
-                    Utils.openDirectory(new File(mc.getMinecraftDir(), "infodump"));
+                    FileOpener.open(new File(mc.getMinecraftDir(), "infodump"));
                     Global.accessor = mc;
                 }))
                 .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.achievements", () -> mc.displayScreen(new ScreenAchievements(mc.currentScreen, mc.statsCounter))))
diff --git a/game/client/src/main/java/net/minecraft/client/gui/text/TextFieldEditor.java b/game/client/src/main/java/net/minecraft/client/gui/text/TextFieldEditor.java
index 5e9722250..e40966600 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/text/TextFieldEditor.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/text/TextFieldEditor.java
@@ -1,6 +1,9 @@
 package net.minecraft.client.gui.text;
 
 import com.mojang.logging.LogUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.core.Global;
+import org.lwjgl.glfw.GLFW;
 import org.lwjgl.input.Keyboard;
 
 import net.minecraft.core.util.helper.MathHelper;
@@ -264,9 +267,7 @@ public class TextFieldEditor
     {
         try
         {
-            StringSelection selection = new StringSelection(string);
-            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
-            clipboard.setContents(selection, selection);
+            Global.accessor.copyToClipboard(string);
         }
         catch (Exception e)
         {
@@ -278,11 +279,7 @@ public class TextFieldEditor
     {
         try
         {
-            Transferable trans = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
-            if (trans != null && trans.isDataFlavorSupported(DataFlavor.stringFlavor))
-            {
-                return (String) trans.getTransferData(DataFlavor.stringFlavor);
-            }
+            return Global.accessor.readFromClipboard();
         }
         catch (Exception e)
         {
diff --git a/game/client/src/main/java/net/minecraft/client/input/controller/ControllerInventoryHandler.java b/game/client/src/main/java/net/minecraft/client/input/controller/ControllerInventoryHandler.java
index bfa2ae7d6..d37ea7cf3 100644
--- a/game/client/src/main/java/net/minecraft/client/input/controller/ControllerInventoryHandler.java
+++ b/game/client/src/main/java/net/minecraft/client/input/controller/ControllerInventoryHandler.java
@@ -24,7 +24,7 @@ public class ControllerInventoryHandler {
 		
 		if(controllerInput.buttonA.pressedThisFrame()) {
 			for(Slot slot2 : container.inventorySlots.slots) {
-                LOGGER.debug("{}: {}", slot2.index, slot2.getItem());
+                LOGGER.debug("{}: {}", slot2.index, slot2.getItemStack());
 			}
 		}
 		
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 1a95924fe..cd10afc99 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
@@ -473,6 +473,11 @@ public class PacketHandlerClient extends PacketHandler
     @Override
     public void handleMapChunk(PacketBlockRegionUpdate blockRegionUpdatePacket)
     {
+        for (int x = blockRegionUpdatePacket.xPosition / 16; x <= blockRegionUpdatePacket.xPosition / 16 + blockRegionUpdatePacket.xSize / 16; x++) {
+            for (int z = blockRegionUpdatePacket.zPosition / 16; z <= blockRegionUpdatePacket.zPosition / 16 + blockRegionUpdatePacket.zSize / 16; z++) {
+                worldClientMP.doPreChunk(x, z, true);
+            }
+        }
         worldClientMP.removePositionTypesInBounds(blockRegionUpdatePacket.xPosition, blockRegionUpdatePacket.yPosition, blockRegionUpdatePacket.zPosition, (blockRegionUpdatePacket.xPosition + blockRegionUpdatePacket.xSize) - 1, (blockRegionUpdatePacket.yPosition + blockRegionUpdatePacket.ySize) - 1, (blockRegionUpdatePacket.zPosition + blockRegionUpdatePacket.zSize) - 1);
         worldClientMP.setChunkData(blockRegionUpdatePacket.xPosition, blockRegionUpdatePacket.yPosition, blockRegionUpdatePacket.zPosition, blockRegionUpdatePacket.xSize, blockRegionUpdatePacket.ySize, blockRegionUpdatePacket.zSize, blockRegionUpdatePacket.chunk);
     }
@@ -942,7 +947,7 @@ public class PacketHandlerClient extends PacketHandler
         }
         else if (containerSetslotPacket.windowId == 0 && containerSetslotPacket.itemSlot >= 36 && containerSetslotPacket.itemSlot < 45)
         {
-            ItemStack itemstack = mc.thePlayer.inventorySlots.getSlot(containerSetslotPacket.itemSlot).getItem();
+            ItemStack itemstack = mc.thePlayer.inventorySlots.getSlot(containerSetslotPacket.itemSlot).getItemStack();
             if (containerSetslotPacket.myItemStack != null && (itemstack == null || itemstack.stackSize < containerSetslotPacket.myItemStack.stackSize))
             {
                 containerSetslotPacket.myItemStack.animationsToGo = 5;
diff --git a/game/client/src/main/java/net/minecraft/client/option/GameSettings.java b/game/client/src/main/java/net/minecraft/client/option/GameSettings.java
index 03df1d9c5..af733e962 100644
--- a/game/client/src/main/java/net/minecraft/client/option/GameSettings.java
+++ b/game/client/src/main/java/net/minecraft/client/option/GameSettings.java
@@ -14,6 +14,7 @@ import com.mojang.logging.LogUtils;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.discord.RichPresenceHandlerThread;
+import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.hud.component.HudComponents;
 import net.minecraft.client.input.InputDevice;
 import net.minecraft.client.option.enums.Colorblindness;
@@ -22,7 +23,6 @@ import net.minecraft.core.enums.Difficulty;
 import net.minecraft.client.option.enums.LightmapStyle;
 import net.minecraft.client.option.enums.MipmapType;
 import net.minecraft.client.option.enums.RenderScale;
-import net.minecraft.client.option.enums.TooltipStyle;
 import net.minecraft.core.enums.PlacementMode;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.sound.SoundCategory;
@@ -163,7 +163,7 @@ public class GameSettings {
 	public OptionBoolean fullscreen = new OptionBoolean(this, "fullscreen", Minecraft.isClientASteamDeck());
 	public OptionBoolean borderlessFullscreen = new OptionBoolean(this, "borderlessFullscreen", true);
 	public OptionBoolean startInFullscreen = new OptionBoolean(this, "startInFullscreen", true);
-	public OptionEnum<TooltipStyle> tooltipStyle = new OptionEnum<>(this, "tooltipStyle", TooltipStyle.class);
+	public OptionTooltip tooltipStyle = new OptionTooltip(this, "tooltipStyle", "default");
 	public OptionEnum<LightmapStyle> lightmapStyle = new OptionEnum<>(this, "lightmapStyle", LightmapStyle.class, LightmapStyle.GRAY);
 	public OptionBoolean customLightmap = new OptionBoolean(this, "customLightmap", true);
 	public OptionBoolean fog = new OptionBoolean(this, "fog", true);
@@ -404,6 +404,13 @@ public class GameSettings {
 				return trans.translateKey("options.bloom.high");
 			}
 		}
+		if (option == this.tooltipStyle) {
+			TooltipElement.Style style = TooltipElement.styleMap.get(this.tooltipStyle.value);
+			if (style != null) {
+				return trans.translateKey(style.translationKey);
+			}
+			return "Unknown";
+		}
 		if (option instanceof OptionBoolean) {
 			Boolean flag = (Boolean) option.value;
 			if (flag) {
diff --git a/game/client/src/main/java/net/minecraft/client/option/OptionToggleable.java b/game/client/src/main/java/net/minecraft/client/option/OptionToggleable.java
index 40a12da61..d4dc88641 100644
--- a/game/client/src/main/java/net/minecraft/client/option/OptionToggleable.java
+++ b/game/client/src/main/java/net/minecraft/client/option/OptionToggleable.java
@@ -14,11 +14,11 @@ public abstract class OptionToggleable<E> extends Option<E> implements Toggleabl
 	}
 	
 	@Override
-	public final void toggle() {
+	public void toggle() {
 		this.value = values[(getValueIndex() + 1) % values.length];
 	}
 	
-	public final void toggle(int delta) {
+	public void toggle(int delta) {
 		this.value = values[DynamicTexture.pmod(getValueIndex() + delta, values.length)];
 	}
 	
diff --git a/game/client/src/main/java/net/minecraft/client/option/OptionTooltip.java b/game/client/src/main/java/net/minecraft/client/option/OptionTooltip.java
new file mode 100644
index 000000000..cff0d83a4
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/option/OptionTooltip.java
@@ -0,0 +1,47 @@
+package net.minecraft.client.option;
+
+import net.minecraft.client.gui.TooltipElement;
+import net.minecraft.client.render.dynamictexture.DynamicTexture;
+import net.minecraft.core.util.helper.Toggleable;
+
+public class OptionTooltip extends OptionToggleable<String> implements Toggleable {
+
+    public OptionTooltip(final GameSettings gameSettings, final String name, final String defaultValue) {
+        super(gameSettings, name, defaultValue, null);
+    }
+
+    @Override
+    public void parse(final String string) {
+        this.value = string;
+    }
+
+    @Override
+    public void toggle() {
+        this.value = TooltipElement.stylesIdList.get((getValueIndex() + 1) % size());
+    }
+
+    @Override
+    public void toggle(final int delta) {
+        this.value = TooltipElement.stylesIdList.get(DynamicTexture.pmod(getValueIndex() + delta, size()));
+    }
+
+    @Override
+    public int getValueIndex() {
+        return TooltipElement.stylesIdList.indexOf(this.value);
+    }
+
+    @Override
+    public void setValueWithIndex(final int i) {
+        this.value = TooltipElement.stylesIdList.get(i);
+    }
+
+    @Override
+    public int size() {
+        return TooltipElement.styleMap.size();
+    }
+
+    @Override
+    public boolean isSlider() {
+        return true;
+    }
+}
diff --git a/game/client/src/main/java/net/minecraft/client/render/LightingCache.java b/game/client/src/main/java/net/minecraft/client/render/LightingCache.java
index 77050245e..5c9300f6e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/LightingCache.java
+++ b/game/client/src/main/java/net/minecraft/client/render/LightingCache.java
@@ -42,25 +42,26 @@ final public class LightingCache {
         }
     }
     
-    private float calcBrightness(int x, int y, int z) {
-		float brightness = block.getBlockBrightness(access, x, y, z);
+    private float calcBrightness(final int x, final int y, final int z) {
+        final int blockId = this.access.getBlockId(x, y, z);
+        final Block<?> block = Blocks.getBlock(blockId);
 
-		if(LightmapHelper.isLightmapEnabled() || mc.fullbright) {
-			int lightEmission = block.emission;
-			if(lightEmission >= 15) {
-				return 1.0f;
-			}
-			if(!mc.isAmbientOcclusionEnabled()) {
-				return 1.0f;
-			}
-            Block<?> block = access.getBlock(x, y, z);
-			if(block == null) {
-				return 1.0f;
-			}
-			return 1.0f - block.getAmbientOcclusionStrength(access, x, y, z);
-		}
-		
-		return brightness;
+        if(LightmapHelper.isLightmapEnabled() || this.mc.fullbright) {
+            if(this.block.emission >= 15) {
+                return 1.0f;
+            }
+            if(!this.mc.isAmbientOcclusionEnabled()) {
+                return 1.0f;
+            }
+            if(block == null) {
+                return 1.0f;
+            }
+            return 1.0f - block.getAmbientOcclusionStrength(this.access, x, y, z);
+        }
+        final int emission = Blocks.lightEmission[blockId];
+        final float brightness = this.access.getBrightness(x, y, z, emission);
+
+        return Math.min(brightness, (this.mc.isAmbientOcclusionEnabled() && block != null) ? (1 - block.getAmbientOcclusionStrength(this.access, x, y, z)) : 1);
     }
     
 	public float getBrightness(int relX, int relY, int relZ) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java b/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
index a9ece6d4d..bd0410481 100644
--- a/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
@@ -207,7 +207,7 @@ public class WorldRenderer
             f1 = (int)(mc.activeCamera.getFov() * 100 + 30);
             f1 *= a + (b - a) * partialTick;
         }
-        if(CameraUtil.isUnderLiquid(mc.activeCamera, mc.currentWorld, Material.water, partialTick))
+        if(mc.gameSettings.fovModification.value && CameraUtil.isUnderLiquid(mc.activeCamera, mc.currentWorld, Material.water, partialTick))
         {
             f1 = f1 - 10;
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
index 40e937881..5494b99a4 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
@@ -507,9 +507,9 @@ public class BlockModelDispatcher
             .setAllTextures(BLOCK_TEXTURES, "minecraft:block/piston_steel/face")
             .withCustomItemBounds(0,0,0,1,1,1));
 
-        addDispatch(new BlockModelPistonHead(Blocks.PISTON_HEAD, TextureRegistry.getTexture("minecraft:block/piston/side")).setAllTextures(BLOCK_TEXTURES, "minecraft:block/piston/face"));
+        addDispatch(new BlockModelPistonHead(Blocks.PISTON_HEAD, TextureRegistry.getTexture("minecraft:block/piston/head"), TextureRegistry.getTexture("minecraft:block/piston/shaft")).setAllTextures(BLOCK_TEXTURES, "minecraft:block/piston/face"));
         addDispatch(new BlockModelEmpty<>(Blocks.PISTON_MOVING));
-        addDispatch(new BlockModelPistonHead(Blocks.PISTON_HEAD_STEEL, TextureRegistry.getTexture("minecraft:block/piston_steel/side"), 6/16d).setAllTextures(BLOCK_TEXTURES, "minecraft:block/piston_steel/face"));
+        addDispatch(new BlockModelPistonHead(Blocks.PISTON_HEAD_STEEL, TextureRegistry.getTexture("minecraft:block/piston_steel/head"), TextureRegistry.getTexture("minecraft:block/piston_steel/shaft"), 6/16d, 8d/16d).setAllTextures(BLOCK_TEXTURES, "minecraft:block/piston_steel/face"));
 
         addDispatch(new BlockModelStandard<>(Blocks.NOTEBLOCK).setAllTextures(BLOCK_TEXTURES, "minecraft:block/noteblock"));
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java
index 5eaa60091..341d80797 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java
@@ -15,7 +15,8 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHead> {
-    protected IconCoordinate pistonSide;
+    protected IconCoordinate pistonHead;
+    protected IconCoordinate pistonShaft;
     protected IconCoordinate pistonDry = TextureRegistry.getTexture("minecraft:block/piston/face");
     protected IconCoordinate pistonSticky = TextureRegistry.getTexture("minecraft:block/piston_sticky/face");
     protected IconCoordinate pistonSteel = TextureRegistry.getTexture("minecraft:block/piston_steel/face");
@@ -23,14 +24,17 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
     public IconCoordinate faceTextureOverride;
 
     protected final double headThickness;
-    public BlockModelPistonHead(Block<BlockLogicPistonHead> block, IconCoordinate pistonSide) {
-        this(block, pistonSide, 4/16d);
+    protected final double shaftThickness;
+    public BlockModelPistonHead(final Block<BlockLogicPistonHead> block, final IconCoordinate pistonHead, final IconCoordinate pistonShaft) {
+        this(block, pistonHead, pistonShaft, 4/16d, 4/16d);
     }
 
-    public BlockModelPistonHead(Block<BlockLogicPistonHead> block, IconCoordinate pistonSide, double headThickness) {
+    public BlockModelPistonHead(final Block<BlockLogicPistonHead> block, final IconCoordinate pistonHead, final IconCoordinate pistonShaft, final double headThickness, final double shaftThickness) {
         super(block);
-        this.pistonSide = pistonSide;
+        this.pistonHead = pistonHead;
+        this.pistonShaft = pistonShaft;
         this.headThickness = headThickness;
+        this.shaftThickness = shaftThickness;
     }
 
     @Override
@@ -42,8 +46,8 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
         renderPistonHead(tessellator, worldSource, block, x, y, z, flag);
         renderBlocks.renderAllFaces = false;
     }
-    public void setFaceTextureOverride(@Nullable IconCoordinate faceTexture){
-        faceTextureOverride = faceTexture;
+    public void setFaceTextureOverride(@Nullable final IconCoordinate faceTexture){
+        this.faceTextureOverride = faceTexture;
     }
     protected boolean renderPistonHead(Tessellator tessellator, WorldSource worldSource, Block<BlockLogicPistonHead> block, int x, int y, int z, boolean flag) {
         int metadata = worldSource.getBlockMetadata(x, y, z);
@@ -54,8 +58,8 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
         }else {
         	brightness = renderBlocks.getBlockBrightness(worldSource, x, y, z);
         }
-        float f1 = flag ? 1.0F : 0.5F;
-        double width = flag ? 1 : 1/2d;
+        final float f1 = flag ? 1.0F : 0.5F;
+        final double width = flag ? 1 : 1/2d;
         switch(direction)
         {
             case DOWN: // BOTTOM
@@ -63,29 +67,29 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
                 renderBlocks.uvRotateWest = 3;
                 renderBlocks.uvRotateSouth = 3;
                 renderBlocks.uvRotateNorth = 3;
-                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, headThickness, 1.0F), x, y, z);
-                renderHeadTopBottom(tessellator, x + 0.375F, x + 0.625F, y + headThickness, y + headThickness + f1, z + 0.625F, z + 0.625F, brightness * 0.8F, width);
-                renderHeadTopBottom(tessellator, x + 0.625F, x + 0.375F, y + headThickness, y + headThickness + f1, z + 0.375F, z + 0.375F, brightness * 0.8F, width);
-                renderHeadTopBottom(tessellator, x + 0.375F, x + 0.375F, y + headThickness, y + headThickness + f1, z + 0.375F, z + 0.625F, brightness * 0.6F, width);
-                renderHeadTopBottom(tessellator, x + 0.625F, x + 0.625F, y + headThickness, y + headThickness + f1, z + 0.625F, z + 0.375F, brightness * 0.6F, width);
+                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, this.headThickness, 1.0F), x, y, z);
+                renderHeadTopBottom(tessellator, x + 0.5 - this.shaftThickness/2, x + 0.5 + this.shaftThickness/2, y + this.headThickness, y + this.headThickness + f1, z + 0.5 + this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, brightness * 0.8F, width);
+                renderHeadTopBottom(tessellator, x + 0.5 + this.shaftThickness/2, x + 0.5 - this.shaftThickness/2, y + this.headThickness, y + this.headThickness + f1, z + 0.5 - this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, brightness * 0.8F, width);
+                renderHeadTopBottom(tessellator, x + 0.5 - this.shaftThickness/2, x + 0.5 - this.shaftThickness/2, y + this.headThickness, y + this.headThickness + f1, z + 0.5 - this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, brightness * 0.6F, width);
+                renderHeadTopBottom(tessellator, x + 0.5 + this.shaftThickness/2, x + 0.5 + this.shaftThickness/2, y + this.headThickness, y + this.headThickness + f1, z + 0.5 + this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, brightness * 0.6F, width);
                 break;
 
             case UP: // TOP
-                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 1 - headThickness, 0.0F, 1.0F, 1.0F, 1.0F), x, y, z);
-                renderHeadTopBottom(tessellator, x + 0.375F, x + 0.625F, ((y - headThickness) + 1.0F) - f1, (y - headThickness) + 1.0F, z + 0.625F, z + 0.625F, brightness * 0.8F, width);
-                renderHeadTopBottom(tessellator, x + 0.625F, x + 0.375F, ((y - headThickness) + 1.0F) - f1, (y - headThickness) + 1.0F, z + 0.375F, z + 0.375F, brightness * 0.8F, width);
-                renderHeadTopBottom(tessellator, x + 0.375F, x + 0.375F, ((y - headThickness) + 1.0F) - f1, (y - headThickness) + 1.0F, z + 0.375F, z + 0.625F, brightness * 0.6F, width);
-                renderHeadTopBottom(tessellator, x + 0.625F, x + 0.625F, ((y - headThickness) + 1.0F) - f1, (y - headThickness) + 1.0F, z + 0.625F, z + 0.375F, brightness * 0.6F, width);
+                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 1 - this.headThickness, 0.0F, 1.0F, 1.0F, 1.0F), x, y, z);
+                renderHeadTopBottom(tessellator, x + 0.5 - this.shaftThickness/2, x + 0.5 + this.shaftThickness/2, ((y - this.headThickness) + 1.0F) - f1, (y - this.headThickness) + 1.0F, z + 0.5 + this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, brightness * 0.8F, width);
+                renderHeadTopBottom(tessellator, x + 0.5 + this.shaftThickness/2, x + 0.5 - this.shaftThickness/2, ((y - this.headThickness) + 1.0F) - f1, (y - this.headThickness) + 1.0F, z + 0.5 - this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, brightness * 0.8F, width);
+                renderHeadTopBottom(tessellator, x + 0.5 - this.shaftThickness/2, x + 0.5 - this.shaftThickness/2, ((y - this.headThickness) + 1.0F) - f1, (y - this.headThickness) + 1.0F, z + 0.5 - this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, brightness * 0.6F, width);
+                renderHeadTopBottom(tessellator, x + 0.5 + this.shaftThickness/2, x + 0.5 + this.shaftThickness/2, ((y - this.headThickness) + 1.0F) - f1, (y - this.headThickness) + 1.0F, z + 0.5 + this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, brightness * 0.6F, width);
                 break;
 
             case NORTH: // NORTH
                 renderBlocks.uvRotateSouth = 1;
                 renderBlocks.uvRotateNorth = 2;
-                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, headThickness), x, y, z);
-                renderHeadNorthSouth(tessellator, x + 0.375F, x + 0.375F, y + 0.625F, y + 0.375F, z + headThickness, z + headThickness + f1, brightness * 0.6F, width);
-                renderHeadNorthSouth(tessellator, x + 0.625F, x + 0.625F, y + 0.375F, y + 0.625F, z + headThickness, z + headThickness + f1, brightness * 0.6F, width);
-                renderHeadNorthSouth(tessellator, x + 0.375F, x + 0.625F, y + 0.375F, y + 0.375F, z + headThickness, z + headThickness + f1, brightness * 0.5F, width);
-                renderHeadNorthSouth(tessellator, x + 0.625F, x + 0.375F, y + 0.625F, y + 0.625F, z + headThickness, z + headThickness + f1, brightness, width);
+                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, this.headThickness), x, y, z);
+                renderHeadNorthSouth(tessellator, x + 0.5 - this.shaftThickness/2, x + 0.5 - this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, z + this.headThickness, z + this.headThickness + f1, brightness * 0.6F, width);
+                renderHeadNorthSouth(tessellator, x + 0.5 + this.shaftThickness/2, x + 0.5 + this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, z + this.headThickness, z + this.headThickness + f1, brightness * 0.6F, width);
+                renderHeadNorthSouth(tessellator, x + 0.5 - this.shaftThickness/2, x + 0.5 + this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, z + this.headThickness, z + this.headThickness + f1, brightness * 0.5F, width);
+                renderHeadNorthSouth(tessellator, x + 0.5 + this.shaftThickness/2, x + 0.5 - this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, z + this.headThickness, z + this.headThickness + f1, brightness, width);
                 break;
 
             case SOUTH: // SOUTH
@@ -93,11 +97,11 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
                 renderBlocks.uvRotateNorth = 1;
                 renderBlocks.uvRotateTop = 3;
                 renderBlocks.uvRotateBottom = 3;
-                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 0.0F, 1 - headThickness, 1.0F, 1.0F, 1.0F), x, y, z);
-                renderHeadNorthSouth(tessellator, x + 0.375F, x + 0.375F, y + 0.625F, y + 0.375F, ((z - headThickness) + 1.0F) - f1, (z - headThickness) + 1.0F, brightness * 0.6F, width);
-                renderHeadNorthSouth(tessellator, x + 0.625F, x + 0.625F, y + 0.375F, y + 0.625F, ((z - headThickness) + 1.0F) - f1, (z - headThickness) + 1.0F, brightness * 0.6F, width);
-                renderHeadNorthSouth(tessellator, x + 0.375F, x + 0.625F, y + 0.375F, y + 0.375F, ((z - headThickness) + 1.0F) - f1, (z - headThickness) + 1.0F, brightness * 0.5F, width);
-                renderHeadNorthSouth(tessellator, x + 0.625F, x + 0.375F, y + 0.625F, y + 0.625F, ((z - headThickness) + 1.0F) - f1, (z - headThickness) + 1.0F, brightness, width);
+                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 0.0F, 1 - this.headThickness, 1.0F, 1.0F, 1.0F), x, y, z);
+                renderHeadNorthSouth(tessellator, x + 0.5 - this.shaftThickness/2, x + 0.5 - this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, ((z - this.headThickness) + 1.0F) - f1, (z - this.headThickness) + 1.0F, brightness * 0.6F, width);
+                renderHeadNorthSouth(tessellator, x + 0.5 + this.shaftThickness/2, x + 0.5 + this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, ((z - this.headThickness) + 1.0F) - f1, (z - this.headThickness) + 1.0F, brightness * 0.6F, width);
+                renderHeadNorthSouth(tessellator, x + 0.5 - this.shaftThickness/2, x + 0.5 + this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, ((z - this.headThickness) + 1.0F) - f1, (z - this.headThickness) + 1.0F, brightness * 0.5F, width);
+                renderHeadNorthSouth(tessellator, x + 0.5 + this.shaftThickness/2, x + 0.5 - this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, ((z - this.headThickness) + 1.0F) - f1, (z - this.headThickness) + 1.0F, brightness, width);
                 break;
 
             case WEST: // WEST
@@ -105,11 +109,11 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
                 renderBlocks.uvRotateWest = 2;
                 renderBlocks.uvRotateTop = 2;
                 renderBlocks.uvRotateBottom = 1;
-                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, headThickness, 1.0F, 1.0F), x, y, z);
-                renderHeadEastWest(tessellator, x + headThickness, x + headThickness + f1, y + 0.375F, y + 0.375F, z + 0.625F, z + 0.375F, brightness * 0.5F, width);
-                renderHeadEastWest(tessellator, x + headThickness, x + headThickness + f1, y + 0.625F, y + 0.625F, z + 0.375F, z + 0.625F, brightness, width);
-                renderHeadEastWest(tessellator, x + headThickness, x + headThickness + f1, y + 0.375F, y + 0.625F, z + 0.375F, z + 0.375F, brightness * 0.6F, width);
-                renderHeadEastWest(tessellator, x + headThickness, x + headThickness + f1, y + 0.625F, y + 0.375F, z + 0.625F, z + 0.625F, brightness * 0.6F, width);
+                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, this.headThickness, 1.0F, 1.0F), x, y, z);
+                renderHeadEastWest(tessellator, x + this.headThickness, x + this.headThickness + f1, y + 0.5 - this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, brightness * 0.5F, width);
+                renderHeadEastWest(tessellator, x + this.headThickness, x + this.headThickness + f1, y + 0.5 + this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, brightness, width);
+                renderHeadEastWest(tessellator, x + this.headThickness, x + this.headThickness + f1, y + 0.5 - this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, brightness * 0.6F, width);
+                renderHeadEastWest(tessellator, x + this.headThickness, x + this.headThickness + f1, y + 0.5 + this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, brightness * 0.6F, width);
                 break;
 
             case EAST: // EAST
@@ -117,68 +121,56 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
                 renderBlocks.uvRotateWest = 1;
                 renderBlocks.uvRotateTop = 1;
                 renderBlocks.uvRotateBottom = 2;
-                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(1 - headThickness, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F), x, y, z);
-                renderHeadEastWest(tessellator, ((x - headThickness) + 1.0F) - f1, (x - headThickness) + 1.0F, y + 0.375F, y + 0.375F, z + 0.625F, z + 0.375F, brightness * 0.5F, width);
-                renderHeadEastWest(tessellator, ((x - headThickness) + 1.0F) - f1, (x - headThickness) + 1.0F, y + 0.625F, y + 0.625F, z + 0.375F, z + 0.625F, brightness, width);
-                renderHeadEastWest(tessellator, ((x - headThickness) + 1.0F) - f1, (x - headThickness) + 1.0F, y + 0.375F, y + 0.625F, z + 0.375F, z + 0.375F, brightness * 0.6F, width);
-                renderHeadEastWest(tessellator, ((x - headThickness) + 1.0F) - f1, (x - headThickness) + 1.0F, y + 0.625F, y + 0.375F, z + 0.625F, z + 0.625F, brightness * 0.6F, width);
+                renderBlocks.renderStandardBlock(tessellator, worldSource, this, AABB.getTemporaryBB(1 - this.headThickness, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F), x, y, z);
+                renderHeadEastWest(tessellator, ((x - this.headThickness) + 1.0F) - f1, (x - this.headThickness) + 1.0F, y + 0.5 - this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, brightness * 0.5F, width);
+                renderHeadEastWest(tessellator, ((x - this.headThickness) + 1.0F) - f1, (x - this.headThickness) + 1.0F, y + 0.5 + this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, brightness, width);
+                renderHeadEastWest(tessellator, ((x - this.headThickness) + 1.0F) - f1, (x - this.headThickness) + 1.0F, y + 0.5 - this.shaftThickness/2, y + 0.5 + this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, z + 0.5 - this.shaftThickness/2, brightness * 0.6F, width);
+                renderHeadEastWest(tessellator, ((x - this.headThickness) + 1.0F) - f1, (x - this.headThickness) + 1.0F, y + 0.5 + this.shaftThickness/2, y + 0.5 - this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, z + 0.5 + this.shaftThickness/2, brightness * 0.6F, width);
                 break;
         }
         renderBlocks.resetRenderBlocks();
         return true;
     }
-    private void renderHeadTopBottom(Tessellator tessellator, double xMin, double xMax, double yMin, double yMax, double zMin, double zMax, float brightness, double width)
+    private void renderHeadTopBottom(final Tessellator tessellator, final double xMin, final double xMax, final double yMin, final double yMax, final double zMin, final double zMax, final float brightness, final double width)
     {
-        IconCoordinate i = pistonSide;
-        if(renderBlocks.overrideBlockTexture != null)
-        {
-            i = renderBlocks.overrideBlockTexture;
-        }
-        double uMin = i.getIconUMin();
-        double vMin = i.getIconVMin();
-        double uMax = i.getSubIconU(width);
-        double vMax = i.getSubIconV(1/4f);
+        final IconCoordinate i = renderBlocks.overrideBlockTexture != null ? renderBlocks.overrideBlockTexture : this.pistonShaft;
+        final double uMin = i.getSubIconU(0.5 - this.shaftThickness/2);
+        final double vMin = i.getIconVMin();
+        final double uMax = i.getSubIconU(0.5 + this.shaftThickness/2);
+        final double vMax = i.getSubIconV(width);
         tessellator.setColorOpaque_F(brightness, brightness, brightness);
-        tessellator.addVertexWithUV(xMin, yMax, zMin, uMax, vMin);
-        tessellator.addVertexWithUV(xMin, yMin, zMin, uMin, vMin);
-        tessellator.addVertexWithUV(xMax, yMin, zMax, uMin, vMax);
-        tessellator.addVertexWithUV(xMax, yMax, zMax, uMax, vMax);
+        tessellator.addVertexWithUV(xMin, yMax, zMin, uMax, vMax);
+        tessellator.addVertexWithUV(xMin, yMin, zMin, uMax, vMin);
+        tessellator.addVertexWithUV(xMax, yMin, zMax, uMin, vMin);
+        tessellator.addVertexWithUV(xMax, yMax, zMax, uMin, vMax);
     }
 
-    private void renderHeadNorthSouth(Tessellator tessellator, double xMin, double xMax, double yMin, double yMax, double zMin, double zMax, float brightness, double width)
+    private void renderHeadNorthSouth(final Tessellator tessellator, final double xMin, final double xMax, final double yMin, final double yMax, final double zMin, final double zMax, final float brightness, final double width)
     {
-        IconCoordinate i = pistonSide;
-        if(renderBlocks.overrideBlockTexture != null)
-        {
-            i = renderBlocks.overrideBlockTexture;
-        }
-        double uMin = i.getIconUMin();
-        double vMin = i.getIconVMin();
-        double uMax = i.getSubIconU(width);
-        double vMax = i.getSubIconV(1/4f);
+        final IconCoordinate i = renderBlocks.overrideBlockTexture != null ? renderBlocks.overrideBlockTexture : this.pistonShaft;
+        final double uMin = i.getSubIconU(0.5 - this.shaftThickness/2);
+        final double vMin = i.getIconVMin();
+        final double uMax = i.getSubIconU(0.5 + this.shaftThickness/2);
+        final double vMax = i.getSubIconV(width);
         tessellator.setColorOpaque_F(brightness, brightness, brightness);
-        tessellator.addVertexWithUV(xMin, yMin, zMax, uMax, vMin);
-        tessellator.addVertexWithUV(xMin, yMin, zMin, uMin, vMin);
-        tessellator.addVertexWithUV(xMax, yMax, zMin, uMin, vMax);
-        tessellator.addVertexWithUV(xMax, yMax, zMax, uMax, vMax);
+        tessellator.addVertexWithUV(xMin, yMin, zMax, uMax, vMax);
+        tessellator.addVertexWithUV(xMin, yMin, zMin, uMax, vMin);
+        tessellator.addVertexWithUV(xMax, yMax, zMin, uMin, vMin);
+        tessellator.addVertexWithUV(xMax, yMax, zMax, uMin, vMax);
     }
 
-    private void renderHeadEastWest(Tessellator tessellator, double xMin, double xMax, double yMin, double yMax, double zMin, double zMax, float brightness, double width)
+    private void renderHeadEastWest(final Tessellator tessellator, final double xMin, final double xMax, final double yMin, final double yMax, final double zMin, final double zMax, final float brightness, final double width)
     {
-        IconCoordinate i = pistonSide;
-        if(renderBlocks.overrideBlockTexture != null)
-        {
-            i = renderBlocks.overrideBlockTexture;
-        }
-        double uMin = i.getIconUMin();
-        double vMin = i.getIconVMin();
-        double uMax = i.getSubIconU(width);
-        double vMax = i.getSubIconV(1/4f);
+        final IconCoordinate i = renderBlocks.overrideBlockTexture != null ? renderBlocks.overrideBlockTexture : this.pistonShaft;
+        final double uMin = i.getSubIconU(0.5 - this.shaftThickness/2);
+        final double vMin = i.getIconVMin();
+        final double uMax = i.getSubIconU(0.5 + this.shaftThickness/2);
+        final double vMax = i.getSubIconV(width);
         tessellator.setColorOpaque_F(brightness, brightness, brightness);
-        tessellator.addVertexWithUV(xMax, yMin, zMin, uMax, vMin);
-        tessellator.addVertexWithUV(xMin, yMin, zMin, uMin, vMin);
-        tessellator.addVertexWithUV(xMin, yMax, zMax, uMin, vMax);
-        tessellator.addVertexWithUV(xMax, yMax, zMax, uMax, vMax);
+        tessellator.addVertexWithUV(xMax, yMin, zMin, uMax, vMax);
+        tessellator.addVertexWithUV(xMin, yMin, zMin, uMax, vMin);
+        tessellator.addVertexWithUV(xMin, yMax, zMax, uMin, vMin);
+        tessellator.addVertexWithUV(xMax, yMax, zMax, uMin, vMax);
     }
     @Override
     public boolean shouldItemRender3d() {
@@ -187,23 +179,23 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
     @Override
     public @Nullable IconCoordinate getBlockTextureFromSideAndMetadata(Side side, int data)
     {
-        Direction direction = BlockLogicPistonHead.getDirectionFromMeta(data);
+        final Direction direction = BlockLogicPistonHead.getDirectionFromMeta(data);
         if(side.getDirection() == direction)
         {
-            if(faceTextureOverride != null)
+            if(this.faceTextureOverride != null)
             {
-                return faceTextureOverride;
+                return this.faceTextureOverride;
             }
             switch (BlockLogicPistonHead.getPistonType(data)) {
                 case BlockLogicPistonHead.TYPE_NORMAL:
-                    return pistonDry;
+                    return this.pistonDry;
                 case BlockLogicPistonHead.TYPE_STICKY:
-                    return pistonSticky;
+                    return this.pistonSticky;
                 case BlockLogicPistonHead.TYPE_STEEL:
-                    return pistonSteel;
+                    return this.pistonSteel;
             }
         }
-        boolean isSteel = block == Blocks.PISTON_HEAD_STEEL; // Todo this is just awful
-        return side.getDirection() != direction.getOpposite() ? pistonSide : ((isSteel) ? pistonSteel : pistonDry); // TODO remove this horrid ternary
+        final boolean isSteel = this.block == Blocks.PISTON_HEAD_STEEL; // Todo this is just awful
+        return side.getDirection() != direction.getOpposite() ? this.pistonHead : ((isSteel) ? this.pistonSteel : this.pistonDry); // TODO remove this horrid ternary
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/RenderBlocks.java b/game/client/src/main/java/net/minecraft/client/render/block/model/RenderBlocks.java
index 097fe7176..14fea3262 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/RenderBlocks.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/RenderBlocks.java
@@ -428,10 +428,10 @@ public final class RenderBlocks
         double d10 = d6;
         if(uvRotateBottom == 2)
         {
-            d3 = tex.getSubIconU(bounds.minX);
+            d3 = tex.getSubIconU(bounds.minZ);
             d5 = tex.getSubIconV(1 - bounds.maxX);
             d4 = tex.getSubIconU(bounds.maxZ);
-            d6 = tex.getSubIconV(1 - bounds.minZ);
+            d6 = tex.getSubIconV(1 - bounds.minX);
             d9 = d5;
             d10 = d6;
             d7 = d3;
diff --git a/game/client/src/main/java/net/minecraft/client/render/texture/meta/gui/GuiTextureProperties.java b/game/client/src/main/java/net/minecraft/client/render/texture/meta/gui/GuiTextureProperties.java
index 28ae55403..7a4ef415b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texture/meta/gui/GuiTextureProperties.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texture/meta/gui/GuiTextureProperties.java
@@ -1,5 +1,8 @@
 package net.minecraft.client.render.texture.meta.gui;
 
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
 public class GuiTextureProperties {
     public static final String TYPE_STRETCH = "stretch";
     public static final String TYPE_TILE = "tile";
@@ -11,7 +14,7 @@ public class GuiTextureProperties {
     public final Border border;
     public final boolean stretchInner;
 
-    public GuiTextureProperties(String type, int width, int height, Border border, boolean stretchInner) {
+    public GuiTextureProperties(@NotNull final String type, final int width, final int height, @Nullable final Border border, final boolean stretchInner) {
         this.type = type;
         this.width = width;
         this.height = height;
@@ -25,11 +28,11 @@ public class GuiTextureProperties {
         public final int right;
         public final int bottom;
 
-        public Border(int size) {
-            left = top = right = bottom = size;
+        public Border(final int size) {
+            this.left = this.top = this.right = this.bottom = size;
         }
 
-        public Border(int left, int top, int right, int bottom) {
+        public Border(final int left, final int top, final int right, final int bottom) {
             this.left = left;
             this.top = top;
             this.right = right;
diff --git a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java
index 1d9ab4b49..f4f856b27 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java
@@ -14,6 +14,7 @@ import java.util.stream.Stream;
 import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.holiday.Holidays;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 
 public abstract class TexturePack {
@@ -44,7 +45,7 @@ public abstract class TexturePack {
 	{
 	}
 
-	public InputStream getResourceAsStream(String s)
+	public @Nullable InputStream getResourceAsStream(String s)
 	{
 		if (Holidays.getCurrentThemedHoliday() != null && Minecraft.getMinecraft().gameSettings.enableHolidayTextures.value) {
 			assert Holidays.getCurrentThemedHoliday().getCustomResourcesSubPath() != null : "Current themed holiday must have a theme!";
diff --git a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
index b24352f5f..6e3a23f1b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
@@ -2,6 +2,7 @@ package net.minecraft.client.render.texturepack;
 
 import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.keyboard.KeyboardLayout;
 import net.minecraft.client.render.Font;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
@@ -102,6 +103,7 @@ public class TexturePackList
 		BlockModelDispatcher.getInstance().reload();
 		ItemModelDispatcher.getInstance().reload();
 		KeyboardLayout.defaultLayout = new KeyboardLayout();
+		TooltipElement.reloadStyles(this);
 	}
 
 	public boolean updateAvailableTexturePacks() {
diff --git a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererSign.java b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererSign.java
index 7696d6599..bfdb6820e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererSign.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererSign.java
@@ -11,6 +11,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.util.helper.Colors;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicSign;
 import net.minecraft.core.block.entity.TileEntitySign;
 import net.minecraft.core.enums.EnumSignPicture;
@@ -33,11 +34,14 @@ public class TileEntityRendererSign extends TileEntityRenderer<TileEntitySign>
 	public void doRender(Tessellator tessellator, TileEntitySign tileEntity, double x, double y, double z,
                          float partialTick)
     {
+        Block<?> block = tileEntity.getBlock();
+        if (block == null || !(block.getLogic() instanceof BlockLogicSign)) return; // Check to make sure the block for the entity is present before rendering, some edge cases have the tile entity loaded before the block data and can cause a crash
+
         GL11.glEnable(GL12.GL_RESCALE_NORMAL);
         GL11.glPushMatrix();
         float scale = 2/3f;
         GL11.glTranslatef((float)x + 0.5F, (float)y + 0.75F * scale, (float)z + 0.5F);
-        if (((BlockLogicSign) tileEntity.getBlock().getLogic()).isFreeStanding) {
+        if (((BlockLogicSign) block.getLogic()).isFreeStanding) {
             float angle = (float)(tileEntity.getBlockMeta() * 360) / 16F;
             GL11.glRotatef(-angle, 0.0F, 1.0F, 0.0F);
             modelSign.signStick.visible = true;
diff --git a/game/client/src/main/java/net/minecraft/client/render/window/GameWindow.java b/game/client/src/main/java/net/minecraft/client/render/window/GameWindow.java
index a9b0e1cd8..a451d1688 100644
--- a/game/client/src/main/java/net/minecraft/client/render/window/GameWindow.java
+++ b/game/client/src/main/java/net/minecraft/client/render/window/GameWindow.java
@@ -37,4 +37,5 @@ public interface GameWindow {
 
 	CursorShape getCursorShape();
 
+	public long getHandle();
 }
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 adf316453..934ff1da9 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
@@ -374,6 +374,11 @@ public class GameWindowGLFW implements GameWindow {
         }
     }
 
+    @Override
+    public long getHandle() {
+        return this.window;
+    }
+
     public static class MonitorInfo {
 
         public final long handle;
diff --git a/game/client/src/main/java/net/minecraft/client/util/helper/FileOpener.java b/game/client/src/main/java/net/minecraft/client/util/helper/FileOpener.java
new file mode 100644
index 000000000..a78193085
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/util/helper/FileOpener.java
@@ -0,0 +1,88 @@
+package net.minecraft.client.util.helper;
+
+import java.awt.Desktop;
+import java.io.File;
+import java.io.IOException;
+import java.util.Locale;
+
+public final class FileOpener {
+
+    public static boolean toClipboard(String path) {
+        String os = System.getProperty("os.name").toLowerCase(Locale.ROOT);
+
+        if (os.contains("win")) {
+            return (run("powershell", "-Command %s", "Get-ChildItem \"" + path + "\" | Set-Clipboard"));
+        }
+
+        if (os.contains("mac")) {
+            return (run("osascript", "-e %s", "set the clipboard to (read (POSIX file \"" + path + "\") as {«class PNGf»})"));
+        }
+
+        return run("xclip-copyfile", "%s", path);
+    }
+
+    public static void open(File file) {
+
+        if (!openSystem(file.getPath()) && !openDESKTOP(file))
+            System.err.println("unable to open file " + System.getProperty("os.name"));
+    }
+
+    private static boolean openSystem(String what) {
+
+        String os = System.getProperty("os.name").toLowerCase(Locale.ROOT);
+
+        if (os.contains("win")) {
+            return (run("explorer", "%s", what));
+        }
+
+        if (os.contains("mac")) {
+            return (run("open", "%s", what));
+        }
+
+        return run("kde-open", "%s", what) || run("gnome-open", "%s", what) || run("xdg-open", "%s", what);
+
+    }
+
+    private static boolean openDESKTOP(File file) {
+
+        if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) {
+            try {
+                Desktop.getDesktop().open(file);
+                return true;
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return false;
+
+    }
+
+    private static boolean run(String command, String arg, String file) {
+
+        String[] args = arg.split(" ");
+        String[] parts = new String[args.length + 1];
+        parts[0] = command;
+        for (int i = 0; i < args.length; i++) {
+            parts[i + 1] = String.format(args[i], file).trim();
+        }
+
+        System.out.println(String.join(" ", parts));
+
+        try {
+            Process p = Runtime.getRuntime().exec(parts);
+            if (p == null)
+                return false;
+
+            try {
+                if (p.exitValue() == 0)
+                    return true;
+                return false;
+            } catch (IllegalThreadStateException itse) {
+                return true;
+            }
+        } catch (IOException e) {
+            //e.printStackTrace();
+            return false;
+        }
+    }
+}
diff --git a/game/client/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java b/game/client/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java
index 6b41dc830..2127c1808 100644
--- a/game/client/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java
+++ b/game/client/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java
@@ -96,7 +96,7 @@ public class ItemDragHandler extends Gui {
 		}
 		
 		if(slot.mayPlace(draggingItemStack) && slot.enableDragAndPickup()) {
-			if(slot.getItem() == null || slot.getItem().canStackWith(draggingItemStack)) {
+			if(slot.getItemStack() == null || slot.getItemStack().canStackWith(draggingItemStack)) {
 				if(!draggedSlots.contains(slot)) {
 					draggedSlots.add(slot);
 				}
@@ -108,7 +108,7 @@ public class ItemDragHandler extends Gui {
 		if(slot == null) throw new NullPointerException("Slot is null");
 		if(draggingItemStack == null) throw new NullPointerException("Stack is null!");
 
-		ItemStack stack = slot.getItem();
+		ItemStack stack = slot.getItemStack();
 		
 		glDisable(GL_TEXTURE_2D);
 		glEnable(GL_BLEND);
diff --git a/game/client/src/main/java/net/minecraft/client/util/helper/ScreenShot.java b/game/client/src/main/java/net/minecraft/client/util/helper/ScreenShot.java
index 6dbaa8add..a3ac8a4b9 100644
--- a/game/client/src/main/java/net/minecraft/client/util/helper/ScreenShot.java
+++ b/game/client/src/main/java/net/minecraft/client/util/helper/ScreenShot.java
@@ -1,8 +1,10 @@
 package net.minecraft.client.util.helper;
 
-import java.awt.image.BufferedImage;
+import java.awt.image.*;
 import java.io.File;
 import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -10,7 +12,10 @@ import java.util.Date;
 import javax.imageio.ImageIO;
 
 import com.mojang.logging.LogUtils;
+import net.minecraft.client.Minecraft;
 import org.lwjgl.BufferUtils;
+import org.lwjgl.glfw.GLFW;
+import org.lwjgl.opengl.AMDInterleavedElements;
 import org.lwjgl.opengl.GL11;
 
 import com.b100.utils.ImageUtils;
@@ -60,11 +65,14 @@ public class ScreenShot
             BufferedImage bufferedimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
             bufferedimage.setRGB(0, 0, width, height, imageData, 0, width);
             ImageIO.write(bufferedimage, "png", destFile);
+            boolean copiedImage = false;
             try {
-            	ImageUtils.copyImageToClipboard(bufferedimage);
-            }catch (Exception e) {
-                LOGGER.error("Exception copying image to clipboard!", e);
-			}
+                copiedImage = FileOpener.toClipboard(destFile.getAbsolutePath());
+            } catch (Exception ignored) {
+            }
+            if (copiedImage) {
+                return "Saved screenshot as " + destFile.getName() + " and copied to clipboard.";
+            }
             return "Saved screenshot as " + destFile.getName();
         }
         catch(Exception exception)
diff --git a/game/client/src/main/java/net/minecraft/client/world/chunk/provider/ChunkProviderClient.java b/game/client/src/main/java/net/minecraft/client/world/chunk/provider/ChunkProviderClient.java
index 278518b1a..7cc5cfa4b 100644
--- a/game/client/src/main/java/net/minecraft/client/world/chunk/provider/ChunkProviderClient.java
+++ b/game/client/src/main/java/net/minecraft/client/world/chunk/provider/ChunkProviderClient.java
@@ -57,6 +57,7 @@ public class ChunkProviderClient
     public Chunk prepareChunk(int chunkX, int chunkZ)
     {
         ChunkCoordinate chunkcoordintpair = new ChunkCoordinate(chunkX, chunkZ);
+        if (chunkMapping.containsKey(chunkcoordintpair)) return chunkMapping.get(chunkcoordintpair);
         Chunk chunk = new Chunk(worldObj, chunkX, chunkZ);
         chunkMapping.put(chunkcoordintpair, chunk);
         chunk.isLoaded = true;
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/bottom.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/bottom.png
index ff08b5c55..7e597ddb2 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/bottom.png and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/bottom.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/bottom_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/bottom_active.png
index ff08b5c55..f69e24d4b 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/bottom_active.png and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/bottom_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/front.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/front.png
index e4f3fc79a..446dba7aa 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/front.png and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/front.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active.png
index 561fb6357..d62495c38 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active.png and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active_overlay.png
index 759d8910e..ec9aa8026 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active_overlay.png and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active_overlay.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/side.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/side.png
index 512adf1f4..8ebbe8e4e 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/side.png and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/side.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active.png
index 77904f909..0980c03c7 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active.png and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/top.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/top.png
index a6f177184..25d5361f8 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/top.png and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/top.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active.png
index 199439a6c..2e0638446 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active.png and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/block_redstone.png b/game/client/src/main/resources/assets/minecraft/textures/block/block_redstone.png
index 6aff9ad63..9ebc62ffd 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/block_redstone.png and b/game/client/src/main/resources/assets/minecraft/textures/block/block_redstone.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston/head.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston/head.png
new file mode 100644
index 000000000..6fd83d826
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/piston/head.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston/shaft.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston/shaft.png
new file mode 100644
index 000000000..35b8c6db8
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/piston/shaft.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/bottom.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/bottom.png
index 43591381b..4f2881cde 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/bottom.png and b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/bottom.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/face.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/face.png
index 25e28da79..ea5b34f01 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/face.png and b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/face.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/head.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/head.png
new file mode 100644
index 000000000..6ce3cca64
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/head.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/shaft.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/shaft.png
new file mode 100644
index 000000000..c126d1c11
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/shaft.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/side.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/side.png
index 8e35742f8..3d08c0b8f 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/side.png and b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/side.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/top.png b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/top.png
index 1115cffe3..d29305462 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/top.png and b/game/client/src/main/resources/assets/minecraft/textures/block/piston_steel/top.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/pumice.png b/game/client/src/main/resources/assets/minecraft/textures/block/pumice.png
index 107480e3c..60c6c45b6 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/pumice.png and b/game/client/src/main/resources/assets/minecraft/textures/block/pumice.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/pumice_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/pumice_overlay.png
index 5a27b3bad..bf79f701a 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/pumice_overlay.png and b/game/client/src/main/resources/assets/minecraft/textures/block/pumice_overlay.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/border.png
new file mode 100644
index 000000000..8b18f1e61
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/inner.png
new file mode 100644
index 000000000..822d2b7fb
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/battle_ui/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/border.png
new file mode 100644
index 000000000..dd9aeb581
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/inner.png
new file mode 100644
index 000000000..d2f379fcc
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/comfy/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/border.png
new file mode 100644
index 000000000..750481b67
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/inner.png
new file mode 100644
index 000000000..ee22bb02d
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/creep-o-vision/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/border.png
new file mode 100644
index 000000000..4670f70bc
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/border.png.mcmeta
new file mode 100644
index 000000000..2f4038c66
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/border.png.mcmeta
@@ -0,0 +1,15 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border":  {
+                "left": 9,
+                "top": 8,
+                "right": 8,
+                "bottom": 8
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/inner.png
new file mode 100644
index 000000000..093aae960
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/properties.json b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/properties.json
new file mode 100644
index 000000000..82ad0976d
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/crt/properties.json
@@ -0,0 +1,5 @@
+{
+    "padding": {
+        "bottom": 6
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/border.png
new file mode 100644
index 000000000..fa2ee3da4
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/inner.png
new file mode 100644
index 000000000..71dc221bb
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/default/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/border.png
new file mode 100644
index 000000000..ab77d5190
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/inner.png
new file mode 100644
index 000000000..f3c479454
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/detailed/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/border.png
new file mode 100644
index 000000000..cbf466af5
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/inner.png
new file mode 100644
index 000000000..7c56f1c6c
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/interdimensional/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/border.png
new file mode 100644
index 000000000..a4603c8fe
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/border.png.mcmeta
new file mode 100644
index 000000000..28c610590
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 2
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/inner.png
new file mode 100644
index 000000000..fb8bba96c
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/properties.json b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/properties.json
new file mode 100644
index 000000000..2ffb4353e
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/modern/properties.json
@@ -0,0 +1,3 @@
+{
+    "padding": 2
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/border.png
new file mode 100644
index 000000000..1940b1c92
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/inner.png
new file mode 100644
index 000000000..cd1f15785
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/noteblock/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/border.png
new file mode 100644
index 000000000..e8b498451
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/border.png.mcmeta
new file mode 100644
index 000000000..c185504b7
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 24,
+            "height": 24,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/inner.png
new file mode 100644
index 000000000..9e8b3c9ee
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/picnic/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/border.png
new file mode 100644
index 000000000..292664a0d
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/inner.png
new file mode 100644
index 000000000..83ff82b2f
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/planks/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/border.png
new file mode 100644
index 000000000..0108a6c99
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/border.png.mcmeta
new file mode 100644
index 000000000..a44b677e1
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 14,
+            "height": 14,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/inner.png
new file mode 100644
index 000000000..50e619df4
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/redstone_goggles/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/border.png
new file mode 100644
index 000000000..df2f14baf
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/border.png.mcmeta
new file mode 100644
index 000000000..a44b677e1
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 14,
+            "height": 14,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/inner.png
new file mode 100644
index 000000000..adf93ea3d
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/retro/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/border.png
new file mode 100644
index 000000000..38b15a1cc
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/inner.png
new file mode 100644
index 000000000..2e34e21da
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/rpg/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/border.png
new file mode 100644
index 000000000..025559cd4
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/border.png.mcmeta
new file mode 100644
index 000000000..3e3e52985
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 25,
+            "height": 25,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/inner.png
new file mode 100644
index 000000000..576f714ea
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/steve/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/border.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/border.png
new file mode 100644
index 000000000..b5e8f2949
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/border.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/border.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/border.png.mcmeta
new file mode 100644
index 000000000..a44b677e1
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/border.png.mcmeta
@@ -0,0 +1,10 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "nine_slice",
+            "width": 14,
+            "height": 14,
+            "border": 3
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/inner.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/inner.png
new file mode 100644
index 000000000..faac4e4e1
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/inner.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/inner.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/inner.png.mcmeta
new file mode 100644
index 000000000..a54149394
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/stone/inner.png.mcmeta
@@ -0,0 +1,9 @@
+{
+    "gui": {
+        "scaling": {
+            "type": "tile",
+            "width": 8,
+            "height": 8
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/styles.json b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/styles.json
new file mode 100644
index 000000000..447c18010
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/tooltip/styles.json
@@ -0,0 +1,20 @@
+{
+    "styles": [
+        "battle_ui",
+        "comfy",
+        "creep-o-vision",
+        "crt",
+        "default",
+        "detailed",
+        "interdimensional",
+        "modern",
+        "noteblock",
+        "picnic",
+        "planks",
+        "redstone_goggles",
+        "retro",
+        "rpg",
+        "steve",
+        "stone"
+    ]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/title/splashes.txt b/game/client/src/main/resources/assets/minecraft/textures/gui/title/splashes.txt
index ce2a58df7..066430a33 100644
--- a/game/client/src/main/resources/assets/minecraft/textures/gui/title/splashes.txt
+++ b/game/client/src/main/resources/assets/minecraft/textures/gui/title/splashes.txt
@@ -134,7 +134,7 @@ The finest minds of a generation!
 Every copy is personalized!
 Damn fine cherry pie!
 Bee tea, eh!
-This background has an Easter projectileEgg!
+This background has an Easter egg!
 Almost finished!
 Watch out for chest goblins!
 Self-documenting!
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/battle_ui.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/battle_ui.png
deleted file mode 100644
index b16e1afbb..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/battle_ui.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/comfy.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/comfy.png
deleted file mode 100644
index 278ede375..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/comfy.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/creep-o-vision.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/creep-o-vision.png
deleted file mode 100644
index 318c4d415..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/creep-o-vision.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/crt.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/crt.png
deleted file mode 100644
index 0b30f5ddf..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/crt.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/default.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/default.png
deleted file mode 100644
index 51f922ad2..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/default.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/detailed.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/detailed.png
deleted file mode 100644
index 57529379e..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/detailed.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/interdimensional.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/interdimensional.png
deleted file mode 100644
index bb915d4a0..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/interdimensional.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/noteblock.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/noteblock.png
deleted file mode 100644
index 31b5ed0cc..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/noteblock.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/picnic.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/picnic.png
deleted file mode 100644
index d45dd8cfb..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/picnic.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/planks.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/planks.png
deleted file mode 100644
index 588e64cef..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/planks.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/redstone_goggles.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/redstone_goggles.png
deleted file mode 100644
index 3fb520d45..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/redstone_goggles.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/retro.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/retro.png
deleted file mode 100644
index fb4a1fdb3..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/retro.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/rpg.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/rpg.png
deleted file mode 100644
index 867249045..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/rpg.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/steve.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/steve.png
deleted file mode 100644
index 02804ddb9..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/steve.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/stone.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/stone.png
deleted file mode 100644
index ebe54e89c..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/stone.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/template.png b/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/template.png
deleted file mode 100644
index 46b715326..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/gui/tooltip/template.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/adamng047_0.png b/game/client/src/main/resources/bg/adamng047_0.png
deleted file mode 100644
index 0bf5348bf..000000000
Binary files a/game/client/src/main/resources/bg/adamng047_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/armandothethird_0.png b/game/client/src/main/resources/bg/armandothethird_0.png
index 13e83e4a4..b882e3be5 100644
Binary files a/game/client/src/main/resources/bg/armandothethird_0.png and b/game/client/src/main/resources/bg/armandothethird_0.png differ
diff --git a/game/client/src/main/resources/bg/armandothethird_1.png b/game/client/src/main/resources/bg/armandothethird_1.png
index 7755d7015..3396b717a 100644
Binary files a/game/client/src/main/resources/bg/armandothethird_1.png and b/game/client/src/main/resources/bg/armandothethird_1.png differ
diff --git a/game/client/src/main/resources/bg/avix3212_0.png b/game/client/src/main/resources/bg/avix3212_0.png
index 7684018d5..f0744ecae 100644
Binary files a/game/client/src/main/resources/bg/avix3212_0.png and b/game/client/src/main/resources/bg/avix3212_0.png differ
diff --git a/game/client/src/main/resources/bg/backgrounds.json b/game/client/src/main/resources/bg/backgrounds.json
index 6917976fc..4e175900f 100644
--- a/game/client/src/main/resources/bg/backgrounds.json
+++ b/game/client/src/main/resources/bg/backgrounds.json
@@ -1,23 +1,38 @@
 {
 	"replace": false,
 	"backgrounds": [
-		"adamng047_0",
 		"armandothethird_0",
 		"armandothethird_1",
 		"avix3212_0",
+		"betmu_0",
+		"captus04_0",
+		"dakras_0",
+		"floralz_0",
 		"frazzelbones_0",
+		"hen0tic02_0",
 		"hobblerox_0",
+		"hobblerox_1",
+		"hydracl_0",
+		"ikkykrrk_0",
 		"itsifox_0",
+		"kiwind._0",
 		"kristality_0",
 		"pyromancer___0",
+		"redslimeeee_0",
+		"sinecaus_0",
+		"sinecaus_1",
+		"sinecaus_2",
 		"snek8611_0",
+		"sourzombo_0",
 		"sx22_0",
+		"sx22_1",
 		"t3ssed_0",
 		"t3ssed_1",
 		"t3ssed_2",
+		"thaboar_0",
+		"thaboar_1",
 		"timtams72_0",
 		"timtams72_1",
-		"wwolflesbian_0",
-		"default_0"
+		"wwolflesbian_0"
 	]
-}
\ No newline at end of file
+}
diff --git a/game/client/src/main/resources/bg/betmu_0.png b/game/client/src/main/resources/bg/betmu_0.png
new file mode 100644
index 000000000..bfb9e30f8
Binary files /dev/null and b/game/client/src/main/resources/bg/betmu_0.png differ
diff --git a/game/client/src/main/resources/bg/captus04_0.png b/game/client/src/main/resources/bg/captus04_0.png
new file mode 100644
index 000000000..ca37781f5
Binary files /dev/null and b/game/client/src/main/resources/bg/captus04_0.png differ
diff --git a/game/client/src/main/resources/bg/dakras_0.png b/game/client/src/main/resources/bg/dakras_0.png
new file mode 100644
index 000000000..86d7e7451
Binary files /dev/null and b/game/client/src/main/resources/bg/dakras_0.png differ
diff --git a/game/client/src/main/resources/bg/default_0.png b/game/client/src/main/resources/bg/default_0.png
deleted file mode 100644
index c3a860335..000000000
Binary files a/game/client/src/main/resources/bg/default_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/floralz_0.png b/game/client/src/main/resources/bg/floralz_0.png
new file mode 100644
index 000000000..a20dcb800
Binary files /dev/null and b/game/client/src/main/resources/bg/floralz_0.png differ
diff --git a/game/client/src/main/resources/bg/frazzelbones_0.png b/game/client/src/main/resources/bg/frazzelbones_0.png
index a1f2d3b28..06b0c8544 100644
Binary files a/game/client/src/main/resources/bg/frazzelbones_0.png and b/game/client/src/main/resources/bg/frazzelbones_0.png differ
diff --git a/game/client/src/main/resources/bg/hen0tic02_0.png b/game/client/src/main/resources/bg/hen0tic02_0.png
new file mode 100644
index 000000000..a4693680d
Binary files /dev/null and b/game/client/src/main/resources/bg/hen0tic02_0.png differ
diff --git a/game/client/src/main/resources/bg/hobblerox_0.png b/game/client/src/main/resources/bg/hobblerox_0.png
index ca8207b33..6002160ad 100644
Binary files a/game/client/src/main/resources/bg/hobblerox_0.png and b/game/client/src/main/resources/bg/hobblerox_0.png differ
diff --git a/game/client/src/main/resources/bg/hobblerox_1.png b/game/client/src/main/resources/bg/hobblerox_1.png
new file mode 100644
index 000000000..25ac6f42e
Binary files /dev/null and b/game/client/src/main/resources/bg/hobblerox_1.png differ
diff --git a/game/client/src/main/resources/bg/hydracl_0.png b/game/client/src/main/resources/bg/hydracl_0.png
new file mode 100644
index 000000000..c190977ad
Binary files /dev/null and b/game/client/src/main/resources/bg/hydracl_0.png differ
diff --git a/game/client/src/main/resources/bg/ikkykrrk_0.png b/game/client/src/main/resources/bg/ikkykrrk_0.png
new file mode 100644
index 000000000..72b0ec7aa
Binary files /dev/null and b/game/client/src/main/resources/bg/ikkykrrk_0.png differ
diff --git a/game/client/src/main/resources/bg/itsifox_0.png b/game/client/src/main/resources/bg/itsifox_0.png
index e560eb5ae..160e760f0 100644
Binary files a/game/client/src/main/resources/bg/itsifox_0.png and b/game/client/src/main/resources/bg/itsifox_0.png differ
diff --git a/game/client/src/main/resources/bg/kiwind._0.png b/game/client/src/main/resources/bg/kiwind._0.png
new file mode 100644
index 000000000..94f89423d
Binary files /dev/null and b/game/client/src/main/resources/bg/kiwind._0.png differ
diff --git a/game/client/src/main/resources/bg/kristality_0.png b/game/client/src/main/resources/bg/kristality_0.png
index 6475415ca..b73cb2bbf 100644
Binary files a/game/client/src/main/resources/bg/kristality_0.png and b/game/client/src/main/resources/bg/kristality_0.png differ
diff --git a/game/client/src/main/resources/bg/pyromancer___0.png b/game/client/src/main/resources/bg/pyromancer___0.png
index c6c59c8d6..a4ab1f7f1 100644
Binary files a/game/client/src/main/resources/bg/pyromancer___0.png and b/game/client/src/main/resources/bg/pyromancer___0.png differ
diff --git a/game/client/src/main/resources/bg/redslimeeee_0.png b/game/client/src/main/resources/bg/redslimeeee_0.png
new file mode 100644
index 000000000..0e6328661
Binary files /dev/null and b/game/client/src/main/resources/bg/redslimeeee_0.png differ
diff --git a/game/client/src/main/resources/bg/sinecaus_0.png b/game/client/src/main/resources/bg/sinecaus_0.png
new file mode 100644
index 000000000..e25226452
Binary files /dev/null and b/game/client/src/main/resources/bg/sinecaus_0.png differ
diff --git a/game/client/src/main/resources/bg/sinecaus_1.png b/game/client/src/main/resources/bg/sinecaus_1.png
new file mode 100644
index 000000000..d5b3345f7
Binary files /dev/null and b/game/client/src/main/resources/bg/sinecaus_1.png differ
diff --git a/game/client/src/main/resources/bg/sinecaus_2.png b/game/client/src/main/resources/bg/sinecaus_2.png
new file mode 100644
index 000000000..ea5e01a45
Binary files /dev/null and b/game/client/src/main/resources/bg/sinecaus_2.png differ
diff --git a/game/client/src/main/resources/bg/snek8611_0.png b/game/client/src/main/resources/bg/snek8611_0.png
index 89df9f38c..731b658ef 100644
Binary files a/game/client/src/main/resources/bg/snek8611_0.png and b/game/client/src/main/resources/bg/snek8611_0.png differ
diff --git a/game/client/src/main/resources/bg/sourzombo_0.png b/game/client/src/main/resources/bg/sourzombo_0.png
new file mode 100644
index 000000000..9149b0c1d
Binary files /dev/null and b/game/client/src/main/resources/bg/sourzombo_0.png differ
diff --git a/game/client/src/main/resources/bg/sx22_0.png b/game/client/src/main/resources/bg/sx22_0.png
index ca28c8e6e..506ff10ac 100644
Binary files a/game/client/src/main/resources/bg/sx22_0.png and b/game/client/src/main/resources/bg/sx22_0.png differ
diff --git a/game/client/src/main/resources/bg/sx22_1.png b/game/client/src/main/resources/bg/sx22_1.png
new file mode 100644
index 000000000..171b2a816
Binary files /dev/null and b/game/client/src/main/resources/bg/sx22_1.png differ
diff --git a/game/client/src/main/resources/bg/t3ssed_0.png b/game/client/src/main/resources/bg/t3ssed_0.png
index 50a0d601f..3c06ce6e6 100644
Binary files a/game/client/src/main/resources/bg/t3ssed_0.png and b/game/client/src/main/resources/bg/t3ssed_0.png differ
diff --git a/game/client/src/main/resources/bg/t3ssed_1.png b/game/client/src/main/resources/bg/t3ssed_1.png
index 03095417f..028694219 100644
Binary files a/game/client/src/main/resources/bg/t3ssed_1.png and b/game/client/src/main/resources/bg/t3ssed_1.png differ
diff --git a/game/client/src/main/resources/bg/t3ssed_2.png b/game/client/src/main/resources/bg/t3ssed_2.png
index 83461ad0d..aee6b73d5 100644
Binary files a/game/client/src/main/resources/bg/t3ssed_2.png and b/game/client/src/main/resources/bg/t3ssed_2.png differ
diff --git a/game/client/src/main/resources/bg/thaboar_0.png b/game/client/src/main/resources/bg/thaboar_0.png
new file mode 100644
index 000000000..bc950ff7e
Binary files /dev/null and b/game/client/src/main/resources/bg/thaboar_0.png differ
diff --git a/game/client/src/main/resources/bg/thaboar_1.png b/game/client/src/main/resources/bg/thaboar_1.png
new file mode 100644
index 000000000..bb5d8dbcf
Binary files /dev/null and b/game/client/src/main/resources/bg/thaboar_1.png differ
diff --git a/game/client/src/main/resources/bg/timtams72_0.png b/game/client/src/main/resources/bg/timtams72_0.png
index bba3c7a82..b5cfc5a6d 100644
Binary files a/game/client/src/main/resources/bg/timtams72_0.png and b/game/client/src/main/resources/bg/timtams72_0.png differ
diff --git a/game/client/src/main/resources/bg/timtams72_1.png b/game/client/src/main/resources/bg/timtams72_1.png
index 09ca0e891..72bd22187 100644
Binary files a/game/client/src/main/resources/bg/timtams72_1.png and b/game/client/src/main/resources/bg/timtams72_1.png differ
diff --git a/game/client/src/main/resources/bg/wwolflesbian_0.png b/game/client/src/main/resources/bg/wwolflesbian_0.png
index c0eee62bd..eb549e30b 100644
Binary files a/game/client/src/main/resources/bg/wwolflesbian_0.png and b/game/client/src/main/resources/bg/wwolflesbian_0.png differ
diff --git a/game/core/src/main/java/com/b100/utils/ImageUtils.java b/game/core/src/main/java/com/b100/utils/ImageUtils.java
index 6a436f00f..aff20192a 100644
--- a/game/core/src/main/java/com/b100/utils/ImageUtils.java
+++ b/game/core/src/main/java/com/b100/utils/ImageUtils.java
@@ -3,7 +3,6 @@ package com.b100.utils;
 import static com.b100.utils.Utils.*;
 
 import java.awt.Image;
-import java.awt.Toolkit;
 import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
 import java.awt.datatransfer.UnsupportedFlavorException;
@@ -16,11 +15,7 @@ import java.nio.file.Files;
 import javax.imageio.ImageIO;
 
 public abstract class ImageUtils {
-	
-	public static void copyImageToClipboard(BufferedImage image) {
-		Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new TransferableImage(image), null);
-	}
-	
+
 	public static BufferedImage loadExternalImage(String path) {
 		return loadExternalImage(new File(path));
 	}
diff --git a/game/core/src/main/java/net/minecraft/core/MinecraftAccessor.java b/game/core/src/main/java/net/minecraft/core/MinecraftAccessor.java
index cf3160a9b..3cda4836e 100644
--- a/game/core/src/main/java/net/minecraft/core/MinecraftAccessor.java
+++ b/game/core/src/main/java/net/minecraft/core/MinecraftAccessor.java
@@ -28,4 +28,8 @@ public interface MinecraftAccessor
     default Collection<String> getAvailableSoundKeys() {
         return SoundTypes.getSoundIds().values();
     }
+
+    default void copyToClipboard(String str) { }
+
+    default String readFromClipboard() { return ""; }
 }
\ No newline at end of file
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java
index cfa71e5c2..80597d2b7 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java
@@ -81,9 +81,9 @@ public class BlockLogicActivator extends BlockLogicVeryRotatable
         if(flag && (meta & MASK_POWERED) == 0)
         {
             world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
-            world.setBlockMetadata(x, y, z, meta | MASK_POWERED);
+            world.setBlockMetadataWithNotify(x, y, z, meta | MASK_POWERED);
         } else if (!flag){
-            world.setBlockMetadata(x, y, z, meta & ~MASK_POWERED);
+            world.setBlockMetadataWithNotify(x, y, z, meta & ~MASK_POWERED);
         }
     }
 
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 31cb0d1ab..c7129397e 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
@@ -793,7 +793,7 @@ public final class Blocks {
     public static final Block<BlockLogicPistonBase> PISTON_BASE_STICKY = register("piston.base.sticky", "minecraft:block/piston_base_sticky", 521, (BlockLogicSupplier<BlockLogicPistonBase>)b -> new BlockLogicPistonBaseSticky(b, 12))
         .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange()
         .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-    public static final Block<BlockLogicPistonHead> PISTON_HEAD = register("piston.head", "minecraft:block/piston_head", 522, (BlockLogicSupplier<BlockLogicPistonHead>)(b) -> new BlockLogicPistonHead(b, 4/16d))
+    public static final Block<BlockLogicPistonHead> PISTON_HEAD = register("piston.head", "minecraft:block/piston_head", 522, (BlockLogicSupplier<BlockLogicPistonHead>)(b) -> new BlockLogicPistonHead(b, 4/16d, 4/16d))
         .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats().withImmovableFlagSet()
         .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
     public static final Block<BlockLogicPistonMoving> PISTON_MOVING = register("piston.moving", "minecraft:block/piston_moving", 523, BlockLogicPistonMoving::new)
@@ -802,7 +802,7 @@ public final class Blocks {
     public static final Block<BlockLogicPistonBase> PISTON_BASE_STEEL = register("piston.base.steel", "minecraft:block/piston_base_steel", 524, (BlockLogicSupplier<BlockLogicPistonBase>)b -> new BlockLogicPistonBaseSteel(b, 24))
         .withSound(BlockSounds.METAL).withDisabledNeighborNotifyOnMetadataChange()
         .withTags(BlockTags.MINEABLE_BY_PICKAXE);
-    public static final Block<BlockLogicPistonHead> PISTON_HEAD_STEEL = register("piston.head.steel", "minecraft:block/piston_head_steel", 525, (BlockLogicSupplier<BlockLogicPistonHead>)(b) -> new BlockLogicPistonHead(b, 6/16d))
+    public static final Block<BlockLogicPistonHead> PISTON_HEAD_STEEL = register("piston.head.steel", "minecraft:block/piston_head_steel", 525, (BlockLogicSupplier<BlockLogicPistonHead>)(b) -> new BlockLogicPistonHead(b, 6/16d, 8/16d))
         .withSound(BlockSounds.METAL).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats()
         .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java
index 5b20fdef6..de37cda71 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityActivator.java
@@ -13,6 +13,7 @@ import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
@@ -36,13 +37,13 @@ public class TileEntityActivator extends TileEntity implements Container {
     }
 
     @Override
-    public ItemStack getItem(int index)
+    public @Nullable ItemStack getItem(int index)
     {
         return dispenserContents[index];
     }
 
     @Override
-    public ItemStack removeItem(int index, int takeAmount)
+    public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         if(dispenserContents[index] != null)
         {
@@ -119,7 +120,7 @@ public class TileEntityActivator extends TileEntity implements Container {
     }
 
     @Override
-    public void setItem(int index, ItemStack itemstack)
+    public void setItem(int index, @Nullable ItemStack itemstack)
     {
         dispenserContents[index] = itemstack;
         if(itemstack != null && itemstack.stackSize > getMaxStackSize())
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java
index e1555e48e..162af9669 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityChest.java
@@ -15,6 +15,7 @@ import net.minecraft.core.player.inventory.InventorySorter;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 
 public class TileEntityChest extends TileEntity
@@ -34,13 +35,13 @@ public class TileEntityChest extends TileEntity
     }
 
     @Override
-	public ItemStack getItem(int index)
+	public @Nullable ItemStack getItem(int index)
     {
         return chestContents[index];
     }
 
     @Override
-	public ItemStack removeItem(int index, int takeAmount)
+	public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         if(chestContents[index] != null)
         {
@@ -65,7 +66,7 @@ public class TileEntityChest extends TileEntity
     }
 
     @Override
-	public void setItem(int index, ItemStack itemstack)
+	public void setItem(int index, @Nullable ItemStack itemstack)
     {
         chestContents[index] = itemstack;
         if(itemstack != null && itemstack.stackSize > getMaxStackSize())
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java
index d36da668a..02491e749 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityDispenser.java
@@ -14,6 +14,7 @@ import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
@@ -34,13 +35,13 @@ public class TileEntityDispenser extends TileEntity
     }
 
     @Override
-	public ItemStack getItem(int index)
+	public @Nullable ItemStack getItem(int index)
     {
         return dispenserContents[index];
     }
 
     @Override
-	public ItemStack removeItem(int index, int takeAmount)
+	public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         if(dispenserContents[index] != null)
         {
@@ -96,7 +97,7 @@ public class TileEntityDispenser extends TileEntity
     }
 
     @Override
-	public void setItem(int index, ItemStack itemstack)
+	public void setItem(int index, @Nullable ItemStack itemstack)
     {
         dispenserContents[index] = itemstack;
         if(itemstack != null && itemstack.stackSize > getMaxStackSize())
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 9aab9595a..21a1e1195 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
@@ -186,7 +186,7 @@ public class TileEntityFlag extends TileEntity
     }
 
     @Override
-    public ItemStack getItem(int index) {
+    public @Nullable ItemStack getItem(int index) {
         index -= 36;
         if (index < 0 || index >= 3) return null;
         
@@ -194,7 +194,7 @@ public class TileEntityFlag extends TileEntity
     }
 
     @Override
-    public ItemStack removeItem(int index, int takeAmount) {
+    public @Nullable ItemStack removeItem(int index, int takeAmount) {
         index -= 36;
         if (items[index] != null)
         {
@@ -230,7 +230,7 @@ public class TileEntityFlag extends TileEntity
     }
 
     @Override
-    public void setItem(int index, ItemStack stack)
+    public void setItem(int index, @Nullable ItemStack stack)
     {
         index -= 36; // This seems so wrong and will almost certainly cause an issue at some point
         items[index] = stack;
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java
index 2793f0879..943dbdf37 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityFurnace.java
@@ -20,6 +20,7 @@ import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 import java.util.Random;
@@ -46,13 +47,13 @@ public class TileEntityFurnace extends TileEntity
     }
 
     @Override
-	public ItemStack getItem(int index)
+	public @Nullable ItemStack getItem(int index)
     {
         return furnaceItemStacks[index];
     }
 
     @Override
-	public ItemStack removeItem(int index, int takeAmount)
+	public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         if(furnaceItemStacks[index] != null)
         {
@@ -81,7 +82,7 @@ public class TileEntityFurnace extends TileEntity
     }
 
     @Override
-	public void setItem(int index, ItemStack itemstack)
+	public void setItem(int index, @Nullable ItemStack itemstack)
     {
         furnaceItemStacks[index] = itemstack;
         if(itemstack != null && itemstack.stackSize > getMaxStackSize())
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java
index dbab2da7e..1fceada04 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityTrommel.java
@@ -57,13 +57,13 @@ public class TileEntityTrommel extends TileEntity
     }
 
     @Override
-	public ItemStack getItem(int index)
+	public @Nullable ItemStack getItem(int index)
     {
         return itemStacks[index];
     }
 
     @Override
-	public ItemStack removeItem(int index, int takeAmount)
+	public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         if(itemStacks[index] != null)
         {
@@ -86,7 +86,7 @@ public class TileEntityTrommel extends TileEntity
     }
 
     @Override
-	public void setItem(int index, ItemStack itemstack)
+	public void setItem(int index, @Nullable ItemStack itemstack)
     {
         itemStacks[index] = itemstack;
         if(itemstack != null && itemstack.stackSize > getMaxStackSize())
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonHead.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonHead.java
index 8d031144e..cd1757f62 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonHead.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonHead.java
@@ -24,11 +24,13 @@ public class BlockLogicPistonHead extends BlockLogic
     public static final int TYPE_STEEL = 2;
 
     private final double headThickness;
-    public BlockLogicPistonHead(Block<?> block, double headThickness)
+    private final double shaftThickness;
+    public BlockLogicPistonHead(final Block<?> block, final double headThickness, final double shaftThickness)
     {
         super(block, Material.piston);
         block.withHardness(0.5F);
         this.headThickness = headThickness;
+        this.shaftThickness = shaftThickness;
     }
 
     @Override
@@ -80,33 +82,33 @@ public class BlockLogicPistonHead extends BlockLogic
     }
 
     @Override
-    public void getCollidingBoundingBoxes(World world, int x, int y, int z, AABB aabb, ArrayList<AABB> aabbList)
+    public void getCollidingBoundingBoxes(final World world, final int x, final int y, final int z, final AABB aabb, final ArrayList<AABB> aabbList)
     {
         switch(getDirectionFromMeta(world.getBlockMetadata(x, y, z)))
         {
             case DOWN:
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, headThickness, 1.0F).move(x, y, z), aabbList);
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.375F, headThickness, 0.375F, 0.625F, 1 + headThickness, 0.625F).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, this.headThickness, 1.0F).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.5 - this.shaftThickness/2, this.headThickness, 0.5 - this.shaftThickness/2, 0.5 + this.shaftThickness/2, 1 + this.headThickness, 0.5 + this.shaftThickness/2).move(x, y, z), aabbList);
                 break;
             case UP:
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 1 - headThickness, 0.0F, 1.0F, 1.0F, 1.0F).move(x, y, z), aabbList);
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.375F, -headThickness, 0.375F, 0.625F, 1 - headThickness, 0.625F).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 1 - this.headThickness, 0.0F, 1.0F, 1.0F, 1.0F).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.5 - this.shaftThickness/2, -this.headThickness, 0.5 - this.shaftThickness/2, 0.5 + this.shaftThickness/2, 1 - this.headThickness, 0.5 + this.shaftThickness/2).move(x, y, z), aabbList);
                 break;
             case NORTH:
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, headThickness).move(x, y, z), aabbList);
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(headThickness, 0.375F, headThickness, 1 - headThickness, 0.625F, 1 + headThickness).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, this.headThickness).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.5 - this.shaftThickness/2, 0.5 - this.shaftThickness/2, this.headThickness, 0.5 + this.shaftThickness/2, 0.5 + this.shaftThickness/2, 1 + this.headThickness).move(x, y, z), aabbList);
                 break;
             case SOUTH:
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 0.0F, 1 - headThickness, 1.0F, 1.0F, 1.0F).move(x, y, z), aabbList);
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(headThickness, 0.375F, -headThickness, 1 - headThickness, 0.625F, 1 - headThickness).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 0.0F, 1 - this.headThickness, 1.0F, 1.0F, 1.0F).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.5 - this.shaftThickness/2, 0.5 - this.shaftThickness/2, -this.headThickness, 0.5 + this.shaftThickness/2, 0.5 + this.shaftThickness/2, 1 - this.headThickness).move(x, y, z), aabbList);
                 break;
             case WEST:
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, headThickness, 1.0F, 1.0F).move(x, y, z), aabbList);
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(headThickness, 0.375F, headThickness, 1 + headThickness, 0.625F, 1 - headThickness).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, this.headThickness, 1.0F, 1.0F).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(this.headThickness, 0.5 - this.shaftThickness/2, 0.5 - this.shaftThickness/2, 1 + this.headThickness, 0.5 + this.shaftThickness/2, 0.5 + this.shaftThickness/2).move(x, y, z), aabbList);
                 break;
             case EAST:
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(1 - headThickness, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F).move(x, y, z), aabbList);
-                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(-headThickness, 0.375F, headThickness, 1 - headThickness, 0.625F, 1 - headThickness).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(1 - this.headThickness, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F).move(x, y, z), aabbList);
+                addIntersectingBoundingBox(aabb, AABB.getTemporaryBB(-this.headThickness, 0.5 - this.shaftThickness/2, 0.5 - this.shaftThickness/2, 1 - this.headThickness, 0.5 + this.shaftThickness/2, 0.5 + this.shaftThickness/2).move(x, y, z), aabbList);
                 break;
         }
     }
@@ -118,17 +120,17 @@ public class BlockLogicPistonHead extends BlockLogic
         switch(getDirectionFromMeta(l))
         {
             case DOWN:
-                return AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, headThickness, 1.0F);
+                return AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, this.headThickness, 1.0F);
             case UP:
-                return AABB.getTemporaryBB(0.0F, 1 - headThickness, 0.0F, 1.0F, 1.0F, 1.0F);
+                return AABB.getTemporaryBB(0.0F, 1 - this.headThickness, 0.0F, 1.0F, 1.0F, 1.0F);
             case NORTH:
-                return AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, headThickness);
+                return AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, this.headThickness);
             case SOUTH:
-                return AABB.getTemporaryBB(0.0F, 0.0F, 1 - headThickness, 1.0F, 1.0F, 1.0F);
+                return AABB.getTemporaryBB(0.0F, 0.0F, 1 - this.headThickness, 1.0F, 1.0F, 1.0F);
             case WEST:
-                return AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, headThickness, 1.0F, 1.0F);
+                return AABB.getTemporaryBB(0.0F, 0.0F, 0.0F, this.headThickness, 1.0F, 1.0F);
             case EAST:
-                return AABB.getTemporaryBB(1 - headThickness, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+                return AABB.getTemporaryBB(1 - this.headThickness, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
         }
         return super.getBlockBoundsFromState(world, x, y, z);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/Entity.java b/game/core/src/main/java/net/minecraft/core/entity/Entity.java
index a01d44a32..fa2f5ad7f 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/Entity.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/Entity.java
@@ -1250,7 +1250,7 @@ public abstract class Entity
 
         entityRiderYawDelta -= yaw;
         //entityRiderPitchDelta -= pitch;
-        if(turnWithVehicle && false) yRot += yaw;
+        if(turnWithVehicle) yRot += yaw;
         //rotationPitch += pitch;
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/Mob.java b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
index 8b8c47d2f..f7d6a20ad 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/Mob.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
@@ -543,7 +543,9 @@ public abstract class Mob extends Entity
             prevBonusHealth = bonusHealth;
             heartsFlashTime = heartsHalvesLife;
             damageEntity(damage, type);
-            hurtTime = maxHurtTime = 10;
+            if (damage > 0) {
+                hurtTime = maxHurtTime = 10;
+            }
         }
         attackedAtYaw = 0.0F;
         if(flag)
@@ -575,7 +577,7 @@ public abstract class Mob extends Entity
             }
             onDeath(attacker);
         } else
-        if(flag)
+        if(flag && damage > 0)
         {
         	playHurtSound();
         }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
index fa8145cbe..c0d278226 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
@@ -4,7 +4,6 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.IItemHolding;
 import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.MobPathfinder;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.entity.projectile.ProjectileArrow;
 import net.minecraft.core.item.ItemFood;
@@ -313,15 +312,15 @@ public class MobWolf extends MobAnimal implements IItemHolding
             setTarget(null);
         }
 
-        if(!hasAttacked && !hasPath() && isWolfTamed() && vehicle == null)
+        if(!this.hasAttacked && !hasPath() && isWolfTamed() && this.vehicle == null)
         {
-            Player entityplayer = world.getPlayerEntityByUUID(getWolfOwner());
-            if(entityplayer != null)
+            final Player owner = this.world.getPlayerEntityByUUID(getWolfOwner());
+            if(owner != null)
             {
-                float f = entityplayer.distanceTo(this);
-                if(f > 5F)
+                final float ownerDistance = owner.distanceTo(this);
+                if(ownerDistance > 5F)
                 {
-                    getPathOrWalkableBlock(entityplayer, f);
+                    setPathToOwnerOrTeleport(owner, ownerDistance);
                 }
             } else
             if(isInWater())
@@ -531,21 +530,27 @@ public class MobWolf extends MobAnimal implements IItemHolding
         }
     }
 
-    private void getPathOrWalkableBlock(Entity entity, float f)
+    private void setPathToOwnerOrTeleport(final Entity owner, final float distance)
     {
-        Path pathentity = world.getPathToEntity(this, entity, 16F);
-        if(pathentity == null && f > 12F)
+        final Path path = this.world.getPathToEntity(this, owner, 16F);
+        if(path == null && distance > 12F)
         {
-            int i = MathHelper.floor(entity.x) - 2;
-            int j = MathHelper.floor(entity.z) - 2;
-            int k = MathHelper.floor(entity.bb.minY);
-            for(int l = 0; l <= 4; l++)
+            final int targetX = MathHelper.floor(owner.x);
+            final int targetY = MathHelper.floor(owner.bb.minY);
+            final int targetZ = MathHelper.floor(owner.z);
+            final byte searchRadius = 2;
+            for(int _x = -searchRadius; _x <= searchRadius; _x++)
             {
-                for(int i1 = 0; i1 <= 4; i1++)
+                for(int _z = -searchRadius; _z <= searchRadius; _z++)
                 {
-                    if((l < 1 || i1 < 1 || l > 3 || i1 > 3) && world.isBlockNormalCube(i + l, k - 1, j + i1) && !world.isBlockNormalCube(i + l, k, j + i1) && !world.isBlockNormalCube(i + l, k + 1, j + i1))
+                    if(
+                        (Math.abs(_x) > 1 || Math.abs(_z) > 1) &&  // forbid teleports within a 1 block radius of the player
+                            this.world.isBlockNormalCube(targetX + _x, targetY - 1, targetZ + _z) && // Solid floor
+                            !this.world.isBlockNormalCube(targetX + _x, targetY, targetZ + _z) && // Two blocks of clearance
+                            !this.world.isBlockNormalCube(targetX + _x, targetY + 1, targetZ + _z))
                     {
-                        moveTo((float)(i + l) + 0.5F, k, (float)(j + i1) + 0.5F, yRot, xRot);
+                        moveTo(targetX + _x + 0.5F, targetY, targetZ + _z + 0.5F, this.yRot, this.xRot);
+                        this.fallDistance = 0;
                         return;
                     }
                 }
@@ -554,7 +559,7 @@ public class MobWolf extends MobAnimal implements IItemHolding
 
         } else
         {
-            setPathToEntity(pathentity);
+            setPathToEntity(path);
         }
     }
 
@@ -637,7 +642,7 @@ public class MobWolf extends MobAnimal implements IItemHolding
     @Override
 	protected void attackEntity(@NotNull Entity entity, float distance)
     {
-        if(entity instanceof EntityItem)
+        if(entity instanceof EntityItem || entity == world.getPlayerEntityByUUID(getWolfOwner()))
             return;
         if(distance > 2.0F && distance < 6F && random.nextInt(10) == 0)
         {
@@ -850,7 +855,7 @@ public class MobWolf extends MobAnimal implements IItemHolding
         }
     }
 
-    public UUID getWolfOwner()
+    public @Nullable UUID getWolfOwner()
     {
         return entityData.getUUID(DATA_OWNER_UUID);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
index 5bec715fd..da5eb2dac 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.entity.monster;
 
 import net.minecraft.core.WeightedRandomLootObject;
+import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.MobFlying;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.entity.projectile.ProjectileFireball;
@@ -277,7 +278,11 @@ public class MobGhast extends MobFlying
     @Override
 	public boolean canSpawnHere()
     {
-        return random.nextInt(20) == 0 && super.canSpawnHere() && world.getDifficulty().canHostileMobsSpawn();
+        return
+            this.world.getDifficulty().canHostileMobsSpawn() &&
+            this.random.nextInt(20) == 0 &&
+            BlockTags.NETHER_MOBS_SPAWN.appliesTo(this.world.getBlock(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z))) &&
+            super.canSpawnHere();
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityMinecart.java b/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityMinecart.java
index b821ac823..0f1c5c588 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityMinecart.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/vehicle/EntityMinecart.java
@@ -143,7 +143,7 @@ public class EntityMinecart extends Entity implements Container {
     public void setMeta(int meta) {entityData.set(DATA_META, meta);}
     public int getMeta() {return entityData.getInt(DATA_META);}
 
-    public void setFuel(int fuel) {entityData.set(DATA_FUEL, fuel);}
+    public void setFuel(short fuel) {entityData.set(DATA_FUEL, fuel);}
     public short getFuel() {return entityData.getShort(DATA_FUEL);}
 
 
@@ -273,6 +273,7 @@ public class EntityMinecart extends Entity implements Container {
             pushTime = 0;
         }
 
+
         double _xo = x;
         double _yo = y;
         double _zo = z;
@@ -292,33 +293,8 @@ public class EntityMinecart extends Entity implements Container {
                 setRot(yRot, xRot);
             }
         } else {
-            yd -= 0.08D;
             motionIteration();
             motionIteration();
-
-            int blockX = MathHelper.floor(x);
-            int blockY = MathHelper.floor(y);
-            int blockZ = MathHelper.floor(z);
-            Block<?> block = world.getBlock(blockX, blockY, blockZ);
-            if (block == null || !(block.getLogic() instanceof BlockLogicRail)) {
-                double motionScale = 1;
-
-                if(onGround) {
-                    motionScale = 0.546F;
-                    if(block != null)
-                    {
-                        motionScale = block.friction * 0.91F;
-                    }
-                } else {
-                    motionScale = 0.99;
-                    motionScale = MathHelper.lerp(motionScale, 1f, pushTime);
-                }
-
-                xd *= motionScale;
-                zd *= motionScale;
-
-                move(xd, yd, zd);
-            }
         }
         this.xo = _xo;
         this.yo = _yo;
@@ -331,6 +307,7 @@ public class EntityMinecart extends Entity implements Container {
         xo = x;
         yo = y;
         zo = z;
+        yd -= 0.04D;
         int blockX = MathHelper.floor(x);
         int blockY = MathHelper.floor(y);
         int blockZ = MathHelper.floor(z);
@@ -505,6 +482,21 @@ public class EntityMinecart extends Entity implements Container {
                     }
                 }
             }
+        } else {
+            xd = MathHelper.clamp(xd, -maxSpeed, maxSpeed);
+            zd = MathHelper.clamp(zd, -maxSpeed, maxSpeed);
+
+            if(onGround) {
+                xd *= 0.5D;
+                yd *= 0.5D;
+                zd *= 0.5D;
+            }
+            move(xd, yd, zd);
+            if(!onGround) {
+                xd *= 0.95D;
+                yd *= 0.95D;
+                zd *= 0.95D;
+            }
         }
         xRot = 0.0F;
         double diffX = xo - x;
@@ -537,7 +529,7 @@ public class EntityMinecart extends Entity implements Container {
             passenger = null;
         }
         if(didFurnacePush && random.nextInt(4) == 0) {
-            setFuel(getFuel() - 1);
+            setFuel((short) (getFuel() - 1));
             if(getFuel() < 0) {
                 xPush = 0.0D;
                 zPush = 0.0D;
@@ -792,7 +784,7 @@ public class EntityMinecart extends Entity implements Container {
                     {
                         player.inventory.setItem(player.inventory.getCurrentItemIndex(), null);
                     }
-                    setFuel(getFuel() + (int) ((LookupFuelFurnace.instance.getFuelYield(itemstack.itemID)/1600F) * 1200));
+                    setFuel((short) (getFuel() + ((LookupFuelFurnace.instance.getFuelYield(itemstack.itemID)/1600F) * 1200)));
                 }
                 xPush = x - player.x;
                 zPush = z - player.z;
@@ -866,12 +858,12 @@ public class EntityMinecart extends Entity implements Container {
     }
 
     @Override
-    public ItemStack getItem(int index) {
+    public @Nullable ItemStack getItem(int index) {
         return items[index];
     }
 
     @Override
-    public ItemStack removeItem(int index, int takeAmount) {
+    public @Nullable ItemStack removeItem(int index, int takeAmount) {
         if(items[index] != null) {
             if(items[index].stackSize <= takeAmount) {
                 ItemStack itemstack = items[index];
@@ -889,7 +881,7 @@ public class EntityMinecart extends Entity implements Container {
     }
 
     @Override
-    public void setItem(int index, ItemStack itemstack) {
+    public void setItem(int index, @Nullable ItemStack itemstack) {
         items[index] = itemstack;
         if(itemstack != null && itemstack.stackSize > getMaxStackSize()) {
             itemstack.stackSize = getMaxStackSize();
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandSeed.java b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandSeed.java
index 7e248a3c4..feff7ecb5 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandSeed.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandSeed.java
@@ -3,6 +3,7 @@ package net.minecraft.core.net.command.commands;
 import com.mojang.brigadier.Command;
 import com.mojang.brigadier.CommandDispatcher;
 import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import net.minecraft.core.Global;
 import net.minecraft.core.net.command.CommandManager;
 import net.minecraft.core.net.command.CommandSource;
 
@@ -18,15 +19,8 @@ public class CommandSeed implements CommandManager.CommandRegistry {
                     CommandSource source = c.getSource();
                     source.sendTranslatableMessage("command.commands.seed.success", source.getWorld().getRandomSeed());
                     if (source.getSender() != null) {
-                        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
-                        if (clipboard != null) {
-                            try {
-                                clipboard.setContents(new StringSelection(String.valueOf(source.getWorld().getRandomSeed())), null);
-                                source.sendTranslatableMessage("command.commands.seed.copied_to_clipboard");
-                            } catch (Exception ignored) {
-
-                            }
-                        }
+                        Global.accessor.copyToClipboard(Long.toString(source.getWorld().getRandomSeed()));
+                        source.sendTranslatableMessage("command.commands.seed.copied_to_clipboard");
                     }
                     return Command.SINGLE_SUCCESS;
                 })
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTeleport.java b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTeleport.java
index 4d9198b55..0beeb1bda 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTeleport.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandTeleport.java
@@ -6,6 +6,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
 import com.mojang.brigadier.builder.RequiredArgumentBuilder;
 import com.mojang.brigadier.tree.CommandNode;
 import net.minecraft.core.entity.Entity;
+import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.net.command.CommandManager;
 import net.minecraft.core.net.command.util.CommandHelper;
 import net.minecraft.core.net.command.CommandSource;
@@ -27,7 +28,7 @@ public class CommandTeleport implements CommandManager.CommandRegistry {
                             DoubleCoordinates targetCoordinates = c.getArgument("position", DoubleCoordinates.class);
 
                             if (source.getSender() != null) {
-                                source.getSender().moveTo(targetCoordinates.getX(source), targetCoordinates.getY(source, true), targetCoordinates.getZ(source), source.getSender().yRot, source.getSender().xRot);
+                                source.teleportPlayerToPos(source.getSender(), targetCoordinates.getX(source), targetCoordinates.getY(source, true), targetCoordinates.getZ(source));
                                 source.sendTranslatableMessage("command.commands.teleport.location.success_single_entity", source.getSender().getDisplayName(), targetCoordinates.getX(source), targetCoordinates.getY(source, true), targetCoordinates.getZ(source));
                             } else {
                                 throw CommandExceptions.notInWorld().create();
@@ -44,7 +45,11 @@ public class CommandTeleport implements CommandManager.CommandRegistry {
 
                                     List<? extends Entity> entities = entitySelector.get(source);
                                     for (Entity entity : entities) {
-                                        entity.moveTo(targetCoordinates.getX(source), targetCoordinates.getY(source, true), targetCoordinates.getZ(source), entity.yRot, entity.xRot);
+                                        if (entity instanceof Player) {
+                                            source.teleportPlayerToPos((Player) entity, targetCoordinates.getX(source), targetCoordinates.getY(source, true), targetCoordinates.getZ(source));
+                                        } else {
+                                            entity.moveTo(targetCoordinates.getX(source), targetCoordinates.getY(source, true), targetCoordinates.getZ(source), entity.yRot, entity.xRot);
+                                        }
                                     }
 
                                     double x = targetCoordinates.getX(source);
diff --git a/game/core/src/main/java/net/minecraft/core/net/command/helpers/EntitySelector.java b/game/core/src/main/java/net/minecraft/core/net/command/helpers/EntitySelector.java
index f8d01420f..915d3165c 100644
--- a/game/core/src/main/java/net/minecraft/core/net/command/helpers/EntitySelector.java
+++ b/game/core/src/main/java/net/minecraft/core/net/command/helpers/EntitySelector.java
@@ -56,7 +56,9 @@ public class EntitySelector {
                     entities.add(entity);
                 }
             }
-            return entities.subList(0, Math.min(entities.size(), this.maxResults));
+            List<Entity> list = entities.subList(0, Math.min(entities.size(), this.maxResults));
+            if (list.isEmpty()) throw CommandExceptions.emptySelector().create();
+            return list;
         } else if (this.playerName != null) {
             List<Player> players = new ArrayList<>();
             for (Player player : source.getWorld().players) {
@@ -64,7 +66,9 @@ public class EntitySelector {
                     players.add(player);
                 }
             }
-            return players.subList(0, Math.min(players.size(), this.maxResults));
+            List<Player> list = players.subList(0, Math.min(players.size(), this.maxResults));
+            if (list.isEmpty()) throw CommandExceptions.emptySelector().create();
+            return list;
         }
 
         List<? extends Entity> entities;
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/container/Container.java b/game/core/src/main/java/net/minecraft/core/player/inventory/container/Container.java
index e96edefe4..357d36376 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/container/Container.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/container/Container.java
@@ -2,17 +2,18 @@ package net.minecraft.core.player.inventory.container;
 
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
+import org.jetbrains.annotations.Nullable;
 
 public interface Container
 {
 
     int getContainerSize();
 
-    ItemStack getItem(int index);
+    @Nullable ItemStack getItem(int index);
 
-    ItemStack removeItem(int index, int takeAmount);
+    @Nullable ItemStack removeItem(int index, int takeAmount);
 
-    void setItem(int index, ItemStack itemstack);
+    void setItem(int index, @Nullable ItemStack itemstack);
 
     String getNameTranslationKey();
 
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerCompound.java b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerCompound.java
index 401af74ea..b9896ff91 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerCompound.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerCompound.java
@@ -3,6 +3,7 @@ package net.minecraft.core.player.inventory.container;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.InventorySorter;
+import org.jetbrains.annotations.Nullable;
 
 public class ContainerCompound
     implements Container
@@ -31,7 +32,7 @@ public class ContainerCompound
     }
 
     @Override
-	public ItemStack getItem(int index)
+	public @Nullable ItemStack getItem(int index)
     {
         if(index >= c1.getContainerSize())
         {
@@ -43,7 +44,7 @@ public class ContainerCompound
     }
 
     @Override
-	public ItemStack removeItem(int index, int takeAmount)
+	public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         if(index >= c1.getContainerSize())
         {
@@ -55,7 +56,7 @@ public class ContainerCompound
     }
 
     @Override
-	public void setItem(int index, ItemStack itemstack)
+	public void setItem(int index, @Nullable ItemStack itemstack)
     {
         if(index >= c1.getContainerSize())
         {
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerCrafting.java b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerCrafting.java
index 25748cb99..9e806cdcd 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerCrafting.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerCrafting.java
@@ -3,6 +3,7 @@ package net.minecraft.core.player.inventory.container;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.menu.MenuAbstract;
+import org.jetbrains.annotations.Nullable;
 
 public class ContainerCrafting
     implements Container
@@ -26,7 +27,7 @@ public class ContainerCrafting
     }
 
     @Override
-	public ItemStack getItem(int index)
+	public @Nullable ItemStack getItem(int index)
     {
         if(index >= getContainerSize())
         {
@@ -68,7 +69,7 @@ public class ContainerCrafting
     }
 
     @Override
-	public ItemStack removeItem(int index, int takeAmount)
+	public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         if(items[index] != null)
         {
@@ -93,7 +94,7 @@ public class ContainerCrafting
     }
 
     @Override
-	public void setItem(int index, ItemStack itemstack)
+	public void setItem(int index, @Nullable ItemStack itemstack)
     {
         items[index] = itemstack;
         menu.slotsChanged(this);
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 8fef34a37..6f7dafafd 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
@@ -237,7 +237,7 @@ public class ContainerInventory
     }
 
     @Override
-	public ItemStack removeItem(int index, int takeAmount)
+	public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         ItemStack aitemstack[] = mainInventory;
         if(index >= mainInventory.length)
@@ -266,7 +266,7 @@ public class ContainerInventory
     }
 
     @Override
-	public void setItem(int index, ItemStack itemstack)
+	public void setItem(int index, @Nullable ItemStack itemstack)
     {
         ItemStack aitemstack[] = mainInventory;
         if(index >= aitemstack.length)
@@ -346,7 +346,7 @@ public class ContainerInventory
     }
 
     @Override
-	public ItemStack getItem(int index)
+	public @Nullable ItemStack getItem(int index)
     {
         ItemStack aitemstack[] = mainInventory;
         if(index >= aitemstack.length)
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerResult.java b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerResult.java
index d8fefbe4f..8146062fd 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerResult.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerResult.java
@@ -2,6 +2,7 @@ package net.minecraft.core.player.inventory.container;
 
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
+import org.jetbrains.annotations.Nullable;
 
 public class ContainerResult
     implements Container
@@ -20,7 +21,7 @@ public class ContainerResult
     }
 
     @Override
-	public ItemStack getItem(int index)
+	public @Nullable ItemStack getItem(int index)
     {
         return items[index];
     }
@@ -32,7 +33,7 @@ public class ContainerResult
     }
 
     @Override
-	public ItemStack removeItem(int index, int takeAmount)
+	public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         if(items[index] != null)
         {
@@ -46,7 +47,7 @@ public class ContainerResult
     }
 
     @Override
-	public void setItem(int index, ItemStack itemstack)
+	public void setItem(int index, @Nullable ItemStack itemstack)
     {
         items[index] = itemstack;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerSimple.java b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerSimple.java
index 759b13bf0..6986c5369 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerSimple.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/container/ContainerSimple.java
@@ -3,6 +3,7 @@ package net.minecraft.core.player.inventory.container;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.InventorySorter;
+import org.jetbrains.annotations.Nullable;
 
 public class ContainerSimple
     implements Container
@@ -19,13 +20,13 @@ public class ContainerSimple
     }
 
     @Override
-	public ItemStack getItem(int index)
+	public @Nullable ItemStack getItem(int index)
     {
         return items[index];
     }
 
     @Override
-	public ItemStack removeItem(int index, int takeAmount)
+	public @Nullable ItemStack removeItem(int index, int takeAmount)
     {
         if(items[index] != null)
         {
@@ -50,7 +51,7 @@ public class ContainerSimple
     }
 
     @Override
-	public void setItem(int index, ItemStack itemstack)
+	public void setItem(int index, @Nullable ItemStack itemstack)
     {
         items[index] = itemstack;
         if(itemstack != null && itemstack.stackSize > getMaxStackSize())
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java
index 706d6c50c..f13c7e308 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java
@@ -65,7 +65,7 @@ public abstract class MenuAbstract
 	{
 		List<ItemStack> itemList = new ArrayList<>();
 		for (Slot slot : slots) {
-			itemList.add(slot.getItem());
+			itemList.add(slot.getItemStack());
 		}
 
 		return itemList;
@@ -77,7 +77,7 @@ public abstract class MenuAbstract
 		for(int i = 0; i < slots.size(); i++)
 		{
 
-			ItemStack itemstack = ((Slot) slots.get(i)).getItem();
+			ItemStack itemstack = ((Slot) slots.get(i)).getItemStack();
 			ItemStack itemstack1 = (ItemStack) lastSlots.get(i);
 			if(ItemStack.areItemStacksEqual(itemstack1, itemstack))
 			{
@@ -179,7 +179,7 @@ public abstract class MenuAbstract
 
 		//Used in multiplayer to check if the item the player clicked is the same item on the server
 		ItemStack controlStack = null;
-		ItemStack stackInSlot = slot.getItem();
+		ItemStack stackInSlot = slot.getItemStack();
 		Item itemInSlot = stackInSlot != null ? stackInSlot.getItem() : null;
 		
 		if(stackInSlot != null) {
@@ -286,7 +286,7 @@ public abstract class MenuAbstract
 				if(action == InventoryAction.CREATIVE_GRAB) {
 					ItemStack stack;
 					if(amount > 0) {
-						stack = slot.getItem().copy();
+						stack = slot.getItemStack().copy();
 						stack.stackSize = amount;
 					}else {
 						stack = null;
@@ -295,7 +295,7 @@ public abstract class MenuAbstract
 				}
 				if(action == InventoryAction.CREATIVE_MOVE) {
 					if(amount > 0) {
-						ItemStack stack = slot.getItem().copy();
+						ItemStack stack = slot.getItemStack().copy();
 						stack.stackSize = amount;
 						player.inventory.insertItem(stack, false);
 					}
@@ -378,7 +378,7 @@ public abstract class MenuAbstract
 	}
 	
 	public void handleArmorEquip(Slot slot, Player player) {
-		ItemStack stackInSlot = slot.getItem();
+		ItemStack stackInSlot = slot.getItemStack();
 		if(stackInSlot == null) {
 			return;
 		}
@@ -444,8 +444,8 @@ public abstract class MenuAbstract
 			return;
 		}
 
-		ItemStack slotStack = slot.getItem();
-		ItemStack hotbarStack = hotbarSlot.getItem();
+		ItemStack slotStack = slot.getItemStack();
+		ItemStack hotbarStack = hotbarSlot.getItemStack();
 
 		if(slotStack != null) {
 			slot.set(null);
@@ -470,7 +470,7 @@ public abstract class MenuAbstract
 	 * Handles all MOVE actions
 	 */
 	public void handleItemMove(InventoryAction action, Slot slot, int target, Player player) {
-		ItemStack stackInSlot = slot.getItem();
+		ItemStack stackInSlot = slot.getItemStack();
 
 		if(slot instanceof SlotResult) {
 			handleCrafting(action, (SlotResult) slot, target, player);
@@ -523,7 +523,7 @@ public abstract class MenuAbstract
 				if(slot1 == null) {
 					continue;
 				}
-				ItemStack item = slot1.getItem();
+				ItemStack item = slot1.getItemStack();
 				if(compare(compareStack, item)) {
 					int freeSpace = getFreeSpace(item, targetSlots);
 					if(freeSpace > 0) {
@@ -557,7 +557,7 @@ public abstract class MenuAbstract
 	 * Handle MOVE actions on crafting result slots
 	 */
 	public void handleCrafting(InventoryAction action, SlotResult slot, int target, Player player) {
-		ItemStack itemToCraft = slot.getItem();
+		ItemStack itemToCraft = slot.getItemStack();
 
 		if(itemToCraft == null) {
 			return;
@@ -581,7 +581,7 @@ public abstract class MenuAbstract
 		}
 
 		for(int i=0; i < craftCount; i++) {
-			itemToCraft = slot.getItem();
+			itemToCraft = slot.getItemStack();
 
 			if(itemToCraft == null) {
 				break;
@@ -617,7 +617,7 @@ public abstract class MenuAbstract
 			Slot slot = getSlotFromList(slots, i);
 			if(slot == null) continue;
 
-			ItemStack stackInSlot = slot.getItem();
+			ItemStack stackInSlot = slot.getItemStack();
 			if(stackInSlot == null) {
 				return max;
 			}
@@ -664,7 +664,7 @@ public abstract class MenuAbstract
 				continue;
 			}
 
-			ItemStack slotStack = slot1.getItem();
+			ItemStack slotStack = slot1.getItemStack();
 			if(slotStack == null) {
 				continue;
 			}
@@ -698,7 +698,7 @@ public abstract class MenuAbstract
 		if(action == InventoryAction.CREATIVE_DRAG) {
 			for(int i=0; i < slots.length; i++) {
 				Slot slot = getSlot(slots[i]);
-				if(slot == null || !slot.enableDragAndPickup() || !slot.mayPlace(draggingItemStack) || slot.getItem() != null) {
+				if(slot == null || !slot.enableDragAndPickup() || !slot.mayPlace(draggingItemStack) || slot.getItemStack() != null) {
 					continue;
 				}
 				ItemStack stack = draggingItemStack.copy();
@@ -729,7 +729,7 @@ public abstract class MenuAbstract
 			if(slot == null || !slot.enableDragAndPickup() || !slot.mayPlace(draggingItemStack)) {
 				continue;
 			}
-			ItemStack stackInSlot = slot.getItem();
+			ItemStack stackInSlot = slot.getItemStack();
 
 			int amount = itemsPerSlot;
 			amount = Math.min(amount, slot.getMaxStackSize());
@@ -848,7 +848,7 @@ public abstract class MenuAbstract
 		for(int i = 0; i < targetSlots.size(); i++) {
 			Slot slot = getSlotFromList(targetSlots, i);
 			if(slot == null) continue;
-			ItemStack stackInSlot = slot.getItem();
+			ItemStack stackInSlot = slot.getItemStack();
 
 			if(stackInSlot == null || !slot.mayPlace(stack) || !stack.canStackWith(stackInSlot)) continue;
 
@@ -866,7 +866,7 @@ public abstract class MenuAbstract
 		for(int i = 0; i < targetSlots.size(); i++) {
 			Slot slot = getSlotFromList(targetSlots, i);
 			if(slot == null) continue;
-			ItemStack stackInSlot = slot.getItem();
+			ItemStack stackInSlot = slot.getItemStack();
 
 			if(stackInSlot != null || !slot.mayPlace(stack)) continue;
 
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/slot/Slot.java b/game/core/src/main/java/net/minecraft/core/player/inventory/slot/Slot.java
index 794cba5ef..634b1363b 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/slot/Slot.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/slot/Slot.java
@@ -19,22 +19,22 @@ public class Slot
 	public Slot(final Container container, final int index, final int x, final int y)
 	{
 		this.container = container;
-		slot = index;
+        this.slot = index;
 		this.x = x;
 		this.y = y;
-		discovered = true;
+        this.discovered = true;
 	}
 
 	public void sortSlotInventory() {
-		if (container != null) {
-			container.sortContainer();
+		if (this.container != null) {
+            this.container.sortContainer();
 		}
 	}
 
-	public ItemStack remove(final int i)
+	public @Nullable ItemStack remove(final int i)
 	{
-		if (container.locked(slot)) return null;
-		return container.removeItem(slot, i);
+		if (this.container.locked(this.slot)) return null;
+		return this.container.removeItem(this.slot, i);
 	}
 
 	public @Nullable String getItemIcon()
@@ -44,27 +44,27 @@ public class Slot
 
 	public boolean hasItem()
 	{
-		return getItem() != null;
+		return getItemStack() != null;
 	}
 
 	public int getMaxStackSize()
 	{
-		return container.getMaxStackSize();
+		return this.container.getMaxStackSize();
 	}
 
-	public ItemStack getItem()
+	public @Nullable ItemStack getItemStack()
 	{
-		return container.getItem(slot);
+		return this.container.getItem(this.slot);
 	}
 
 	public boolean isAt(final Container container, final int i)
 	{
-		return container == this.container && i == slot;
+		return container == this.container && i == this.slot;
 	}
 
 	public boolean mayPlace(final ItemStack itemstack)
 	{
-		return container != null && !isLocked();
+		return this.container != null && !isLocked();
 	}
 
 	public void onTake(final ItemStack itemstack)
@@ -74,19 +74,19 @@ public class Slot
 
 	public void setChanged()
 	{
-		container.setChanged();
+        this.container.setChanged();
 	}
 
 	public Container getContainer() {
-		return container;
+		return this.container;
 	}
 
-	public void set(final ItemStack itemstack)
+	public void set(final @Nullable ItemStack itemstack)
 	{
-		container.setItem(slot, itemstack);
+        this.container.setItem(this.slot, itemstack);
 		setChanged();
 
-		if (container instanceof ContainerInventory)
+		if (this.container instanceof ContainerInventory)
 		{
 			final ContainerInventory inventory = (ContainerInventory) this.container;
 
@@ -104,12 +104,12 @@ public class Slot
 		return !isLocked();
 	}
 
-	public boolean getIsDiscovered(Player player){
-		return discovered;
+	public boolean getIsDiscovered(final Player player){
+		return this.discovered;
 	}
 
 	public boolean isLocked() {
-		return container != null && container.locked(slot);
+		return this.container != null && this.container.locked(this.slot);
 	}
 
 }
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotArmor.java b/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotArmor.java
index f1b5492e3..36d7b358c 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotArmor.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotArmor.java
@@ -11,6 +11,7 @@ import net.minecraft.core.item.material.ArmorMaterial;
 import net.minecraft.core.player.inventory.container.ContainerInventory;
 import net.minecraft.core.player.inventory.menu.MenuInventory;
 import net.minecraft.core.player.inventory.container.Container;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -63,7 +64,7 @@ public class SlotArmor extends Slot
         {
         	if (menu.slots.get(i) instanceof SlotArmor)
         	{
-        		ItemStack stack = menu.slots.get(i).getItem();
+        		ItemStack stack = menu.slots.get(i).getItemStack();
         		if (stack != null && (stack.itemID == Items.ARMOR_BOOTS_CHAINMAIL.id || stack.itemID == Items.ARMOR_HELMET_CHAINMAIL.id || stack.itemID == Items.ARMOR_CHESTPLATE_CHAINMAIL.id || stack.itemID == Items.ARMOR_LEGGINGS_CHAINMAIL.id))
 				{
         			count++;
@@ -85,13 +86,13 @@ public class SlotArmor extends Slot
             menu.inventory.player.triggerAchievement(Achievements.ALL_ARMOR_TYPES);
         }
         
-        if (getItem() != null && container instanceof ContainerInventory) {
+        if (getItemStack() != null && container instanceof ContainerInventory) {
             Player player = ((ContainerInventory) container).player;
             player.world.playSoundAtEntity(player, player, "random.equip", 2f, 1f);
         }
     }
 
-    public void set(final ItemStack itemstack)
+    public void set(final @Nullable ItemStack itemstack)
     {
         super.set(itemstack);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotCreative.java b/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotCreative.java
index 2e089d1c0..a59cca1f6 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotCreative.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/slot/SlotCreative.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.player.inventory.slot;
 
 import net.minecraft.core.item.ItemStack;
+import org.jetbrains.annotations.Nullable;
 
 public class SlotCreative extends Slot
 {
@@ -14,7 +15,7 @@ public class SlotCreative extends Slot
 
 
 	@Override
-	public ItemStack remove(final int i)
+	public @Nullable ItemStack remove(final int i)
 	{
 		if (item == null)
 		{
@@ -37,7 +38,7 @@ public class SlotCreative extends Slot
 	}
 
 	@Override
-	public ItemStack getItem()
+	public @Nullable ItemStack getItemStack()
 	{
 		if (item == null)
 		{
@@ -58,7 +59,7 @@ public class SlotCreative extends Slot
 	}
 
 	@Override
-	public void set(final ItemStack itemstack)
+	public void set(final @Nullable ItemStack itemstack)
 	{
 		return;
 	}
diff --git a/game/core/src/main/java/net/minecraft/core/util/helper/Utils.java b/game/core/src/main/java/net/minecraft/core/util/helper/Utils.java
index 5a3df5ad6..7dd1202bf 100644
--- a/game/core/src/main/java/net/minecraft/core/util/helper/Utils.java
+++ b/game/core/src/main/java/net/minecraft/core/util/helper/Utils.java
@@ -40,21 +40,4 @@ public abstract class Utils {
 	public static double floor100(double d) {
 		return ((long) (d * 100)) / 100.0;
 	}
-	
-	public static void openDirectory(File file) {
-		if(!file.exists()) {
-            LOGGER.warn("Can't open directory '{}' because it doesnt exist!", file.getAbsolutePath());
-			return;
-		}
-		if(!file.isDirectory()) {
-            LOGGER.warn("Not a directory: '{}'!", file.getAbsolutePath());
-			return;
-		}
-		try {
-			Desktop.getDesktop().open(file);
-		}catch (Exception e) {
-            LOGGER.error("Error opening directory '{}'!", file.getAbsolutePath(), e);
-		}
-	}
-	
 }
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 0f3e03456..672d41090 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
@@ -2676,7 +2676,7 @@ public class World implements WorldSource {
         return blockId > 0 && block == null && block1.canPlaceBlockOnSide(this, x, y, z, side);
     }
 
-    public Path getPathToEntity(Entity entity, Entity entityToTravelTo, float distance)
+    public @Nullable Path getPathToEntity(Entity entity, Entity entityToTravelTo, float distance)
     {
         int x1 = MathHelper.floor(entity.x);
         int y2 = MathHelper.floor(entity.y);
@@ -2692,7 +2692,7 @@ public class World implements WorldSource {
         return (new PathFinder(chunkcache)).findPath(entity, entityToTravelTo, distance);
     }
 
-    public Path getEntityPathToXYZ(Entity entity, int x, int y, int z, float distance)
+    public @Nullable Path getEntityPathToXYZ(Entity entity, int x, int y, int z, float distance)
     {
         int eBlockX = MathHelper.floor(entity.x);
         int eBlockY = MathHelper.floor(entity.y);
@@ -2801,10 +2801,10 @@ public class World implements WorldSource {
         return null;
     }
 
-    public Player getPlayerEntityByUUID(UUID uuid)
+    public Player getPlayerEntityByUUID(@Nullable final UUID uuid)
     {
-        for (Player player : players) {
-            if (uuid.equals(player.uuid)) {
+        for (final Player player : this.players) {
+            if (player.uuid.equals(uuid)) {
                 return player;
             }
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/pathfinder/PathFinder.java b/game/core/src/main/java/net/minecraft/core/world/pathfinder/PathFinder.java
index 85c6092f5..ce5c8da06 100644
--- a/game/core/src/main/java/net/minecraft/core/world/pathfinder/PathFinder.java
+++ b/game/core/src/main/java/net/minecraft/core/world/pathfinder/PathFinder.java
@@ -8,6 +8,7 @@ import net.minecraft.core.block.material.Material;
 import net.minecraft.core.util.collection.IntHashMap;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.WorldSource;
+import org.jetbrains.annotations.Nullable;
 
 public class PathFinder
 {
@@ -24,17 +25,17 @@ public class PathFinder
         this.worldSource = worldSource;
     }
 
-    public Path findPath(Entity entity, Entity target, float distance)
+    public @Nullable Path findPath(Entity entity, Entity target, float distance)
     {
         return findPath(entity, target.x, target.bb.minY, target.z, distance);
     }
 
-    public Path findPath(Entity entity, int xt, int yt, int zt, float distance)
+    public @Nullable Path findPath(Entity entity, int xt, int yt, int zt, float distance)
     {
         return findPath(entity, (float)xt + 0.5F, (float)yt + 0.5F, (float)zt + 0.5F, distance);
     }
 
-    private Path findPath(Entity entity, double xt, double yt, double zt, float distance)
+    private @Nullable Path findPath(Entity entity, double xt, double yt, double zt, float distance)
     {
         openSet.clear();
         closedSet.clear();
@@ -44,7 +45,7 @@ public class PathFinder
         return findPath(entity, pathpoint, pathpoint1, pathpoint2, distance);
     }
 
-    private Path findPath(Entity entity, Node pathpoint, Node pathpoint1, Node pathpoint2, float f)
+    private @Nullable Path findPath(Entity entity, Node pathpoint, Node pathpoint1, Node pathpoint2, float f)
     {
         pathpoint.g = 0.0F;
         pathpoint.h = pathpoint.distanceTo(pathpoint1);
diff --git a/game/server/src/main/java/net/minecraft/server/net/command/commands/CommandSave.java b/game/server/src/main/java/net/minecraft/server/net/command/commands/CommandSave.java
index 720d1d1d4..632b0e55f 100644
--- a/game/server/src/main/java/net/minecraft/server/net/command/commands/CommandSave.java
+++ b/game/server/src/main/java/net/minecraft/server/net/command/commands/CommandSave.java
@@ -20,9 +20,8 @@ public class CommandSave implements CommandManager.CommandRegistry {
         new DynamicCommandExceptionType(arg -> () -> I18n.getInstance().translateKeyAndFormat("command.commands.save.exception_failure", arg));
 
     public void register(CommandDispatcher<CommandSource> dispatcher) {
-        dispatcher.register
-            (
-                LiteralArgumentBuilder.<CommandSource>literal("save")
+        dispatcher.register(LiteralArgumentBuilder.<CommandSource>literal("save")
+                    .requires(CommandSource::hasAdmin)
                     .then(LiteralArgumentBuilder.<CommandSource>literal("all").executes(c -> {
                         CommandSource source = c.getSource();
                         if (!(source instanceof IServerCommandSource)) throw CommandExceptions.multiplayerWorldOnly().create();
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 f65d39a62..56c12ddb3 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
@@ -690,7 +690,7 @@ public class PacketHandlerServer extends PacketHandler
                 ArrayList<ItemStack> arraylist = new ArrayList<>();
                 for (int i = 0; i < playerEntity.craftingInventory.slots.size(); i++)
                 {
-                    arraylist.add(playerEntity.craftingInventory.slots.get(i).getItem());
+                    arraylist.add(playerEntity.craftingInventory.slots.get(i).getItemStack());
                 }
 
                 playerEntity.updateCraftingInventory(playerEntity.craftingInventory, arraylist);
diff --git a/util/isom/build.gradle.kts b/util/isom/build.gradle.kts
new file mode 100644
index 000000000..d14ca559f
--- /dev/null
+++ b/util/isom/build.gradle.kts
@@ -0,0 +1,70 @@
+import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
+
+plugins {
+    id("java")
+    alias(libs.plugins.shadow)
+}
+
+group = providers.gradleProperty("bta.group").get()
+version = providers.gradleProperty("bta.version").get()
+
+val include: Configuration by configurations.creating
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    // <test dependencies>
+    testImplementation(platform("org.junit:junit-bom:5.10.3"))
+    testImplementation("org.junit.jupiter:junit-jupiter")
+    // </test dependencies>
+
+    implementation(project(":game:core"))?.let { include(it) }
+    implementation(project(":game:client"))?.let { include(it) }
+
+    // <core dependencies>
+    implementation(libs.jetbrains.annotations)?.let { include(it) }
+    implementation(libs.bundles.log4j)?.let { include(it) }
+    implementation(project(":util:nbt"))?.let { include(it) }
+    implementation(project(":util:logging"))?.let { include(it) }
+    // </core dependencies>
+}
+
+//region Tasks
+val buildJar by tasks.registering(ShadowJar::class) {
+    dependsOn(tasks["test"])
+    group = "useless"
+    configurations = listOf(include)
+
+    from(sourceSets["main"].output.classesDirs)
+    from(sourceSets["main"].resources)
+    archiveFileName.set("SeedViewer-$version.jar")
+    manifest {
+        attributes["Main-Class"] = "org.useless.seedviewer.SeedViewerMain"
+        attributes["Implementation-Version"] = version
+    }
+}
+
+val run by tasks.registering(JavaExec::class) {
+    group = "useless"
+
+    mainClass.set("org.useless.seedviewer.SeedViewerMain")
+    classpath += sourceSets["main"].runtimeClasspath
+    jvmArgs = if (arrayOf("Mac OS X", "Darwin").any { System.getProperty("os.name").startsWith(it) }) {
+        listOf("-XstartOnFirstThread", "-Djava.awt.headless=true", "-ea")
+    } else {
+        listOf("-ea")
+    }
+}
+
+//endregion
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_1_8
+    targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+tasks.test {
+    useJUnitPlatform()
+}
\ No newline at end of file
