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 81f67a35c..9930e1db5 100644
--- a/game/client/src/main/java/net/minecraft/client/Minecraft.java
+++ b/game/client/src/main/java/net/minecraft/client/Minecraft.java
@@ -495,10 +495,10 @@ public class Minecraft
         this.terrainRenderer = new TerrainRendererMultiDraw(this);
 
         setRenderer(new ShadersRenderer(this));
-        Shaders.init();
 
         TextureRegistry.init();
         this.texturePackList.init();
+        Shaders.init();
         EntityGeometryMojangData.Cache.reload(this.texturePackList);
 
         TooltipElement.reloadStyles(this.texturePackList);
@@ -1526,6 +1526,16 @@ public class Minecraft
                             displayInGameMenu();
                         } else if (GameSettings.KEY_COMMAND.isPressed()) {
                             displayScreen(new ScreenChat("/"));
+                        } else if (GameSettings.KEY_TOGGLE_FRAME_LIMIT.isPressEvent()) {
+                            if (GameSettings.ENABLE_VSYNC.value) {
+                                GameSettings.ENABLE_VSYNC.set(false);
+                                GameSettings.ENABLE_VSYNC.onUpdate();
+                                GameSettings.CUSTOM_FPS_LIMIT.set(0);
+                            } else {
+                                GameSettings.ENABLE_VSYNC.set(true);
+                                GameSettings.ENABLE_VSYNC.onUpdate();
+                                GameSettings.CUSTOM_FPS_LIMIT.set(0);
+                            }
                         } else {
                             checkBoundInputs(InputDevice.keyboard);
                         }
@@ -2322,7 +2332,7 @@ public class Minecraft
             if (spawnCoordinates != null) {
                 bedSpawnCoordinates = Player.getValidBedSpawnCoordinates(this.currentWorld, spawnCoordinates);
                 if (bedSpawnCoordinates == null) {
-                    this.thePlayer.sendTranslatedChatMessage("messages.bed.notValid");
+                    this.thePlayer.sendStatusMessageTranslated("messages.bed.notValid");
                 }
             }
         }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/Gui.java b/game/client/src/main/java/net/minecraft/client/gui/Gui.java
index a5630757e..954bca89f 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/Gui.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/Gui.java
@@ -84,6 +84,24 @@ public class Gui {
         GLRenderer.popFrame();
     }
 
+    public void drawRect(@NotNull TessellatorGeneral t, int minX, int minY, int maxX, int maxY, final int argb) {
+        if (minX < maxX) {
+            final int temp = minX;
+            minX = maxX;
+            maxX = temp;
+        }
+        if (minY < maxY) {
+            final int temp = minY;
+            minY = maxY;
+            maxY = temp;
+        }
+        t.setColor1i(argb);
+        t.addVertex(minX, maxY, 0);
+        t.addVertex(maxX, maxY, 0);
+        t.addVertex(maxX, minY, 0);
+        t.addVertex(minX, minY, 0);
+    }
+
     public void drawRectDouble(double minX, double minY, double maxX, double maxY, final int argb) {
         if (minX < maxX) {
             final double temp = minX;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenConsole.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenConsole.java
index b8a039991..dad670792 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenConsole.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenConsole.java
@@ -65,11 +65,14 @@ public class ScreenConsole extends Screen {
                 this.scroll = 0;
             }
 
+            var font = Minecraft.getMinecraft().font;
+            font.startDrawingDeferred();
             final int lines = Math.min(heightLines, WORKED_LINES.size() - this.scroll);
             for (int i = lines - 1; i >= 0; i--) {
                 final @NotNull String line = WORKED_LINES.get((WORKED_LINES.size() - 1) - (i + this.scroll));
-                Minecraft.getMinecraft().font.render(line, x, y + getHeight(numLines) - LINE_HEIGHT - LINE_HEIGHT * i).setFont(Fonts.MONOSPACE).setColor(0xFF_CF_CF_CF).call();
+                font.render(line, x, y + getHeight(numLines) - LINE_HEIGHT - LINE_HEIGHT * i).setFont(Fonts.MONOSPACE).setColor(0xFF_CF_CF_CF).call();
             }
+            font.draw(this.zLevel);
             renderScrollIndicator(x, y, numLines);
         }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
index 51ae70bf7..ef2f5e185 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
@@ -7,7 +7,6 @@ import java.util.*;
 
 import com.mojang.logging.LogUtils;
 import net.minecraft.client.entity.player.PlayerLocalMultiplayer;
-import net.minecraft.client.gui.chat.ScreenChat;
 import net.minecraft.client.gui.Gui;
 import net.minecraft.client.gui.ScreenPhotoMode;
 import net.minecraft.client.option.GameSettings;
@@ -18,14 +17,13 @@ import net.minecraft.client.render.renderer.BlendFactor;
 import net.minecraft.client.render.renderer.GLRenderer;
 import net.minecraft.client.render.renderer.Shaders;
 import net.minecraft.client.render.renderer.State;
+import net.minecraft.client.render.tessellator.TessellatorShader;
 import net.minecraft.client.render.tessellator.TessellatorTerrainImpl;
 import net.minecraft.core.block.BlockLogicPortal;
-import net.minecraft.core.enums.ChatVisibility;
 import net.minecraft.core.enums.HumanArmorShape;
 import net.minecraft.core.player.gamemode.Gamemodes;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.phys.HitResult;
-import org.jetbrains.annotations.NotNull;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.hud.component.HudComponent;
@@ -49,18 +47,21 @@ import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.lang.I18n;
-import net.minecraft.core.net.ChatLine;
 import net.minecraft.core.net.command.TextFormatting;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.season.Season;
 import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.wind.WindProvider;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL41;
 import org.slf4j.Logger;
 
 public class HudIngame extends Gui {
     public static final float DEBUG_SCALE = 1f;
+    protected static final @NotNull TessellatorGeneral hudTessellater = new TessellatorShader("Hud Tessellator", 8192);
+    protected static final @NotNull StringBuilder hudBuilder = new StringBuilder(256);
+
     private static final Logger LOGGER = LogUtils.getLogger();
     public static final Direction[] directions = new Direction[]{Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST};
 
@@ -89,7 +90,7 @@ public class HudIngame extends Gui {
     public void renderGameOverlay(float partialTicks, boolean flag, int mouseX, int mouseY) {
         if (this.mc.currentScreen instanceof ScreenPhotoMode) return;
 
-        I18n stringtranslate = I18n.getInstance();
+        I18n i18n = I18n.getInstance();
         int width = this.mc.resolution.getScaledWidthScreenCoords();
         int height = this.mc.resolution.getScaledHeightScreenCoords();
         this.mc.worldRenderer.setupScaledResolution();
@@ -190,27 +191,32 @@ public class HudIngame extends Gui {
 
                 int space = 6;
 
-                drawDebugScreenLineRight("Used memory: " + (memUsed * 100L) / memMax + "% (" + memUsed / 1024L / 1024L + "MB) of " + memMax / 1024L / 1024L + "MB");
-                drawDebugScreenLineRight("Allocated memory: " + (memTotal * 100L) / memMax + "% (" + memTotal / 1024L / 1024L + "MB)");
-                drawDebugScreenLineRight("JRE: " + System.getProperty("java.version") + " (" + System.getProperty("java.vendor") + ")");
-                drawDebugScreenLineRight("LWJGL version: " + org.lwjgl.Version.getVersion());
+                hudTessellater.startDrawingQuads();
+                hudBuilder.setLength(0);
+
+                this.fontRenderer.startDrawingDeferred();
+
+                drawDebugScreenLineRight(hudTessellater, hudBuilder.append("Used memory: ").append((memUsed * 100L) / memMax).append("% (").append(memUsed / 1024L / 1024L).append("MB) of ").append(memMax / 1024L / 1024L).append("MB")); hudBuilder.setLength(0);
+                drawDebugScreenLineRight(hudTessellater, hudBuilder.append("Allocated memory: ").append((memTotal * 100L) / memMax).append("% (").append(memTotal / 1024L / 1024L).append("MB)")); hudBuilder.setLength(0);
+                drawDebugScreenLineRight(hudTessellater, hudBuilder.append("JRE: ").append(System.getProperty("java.version")).append(" (").append(System.getProperty("java.vendor")).append(")")); hudBuilder.setLength(0);
+                drawDebugScreenLineRight(hudTessellater, hudBuilder.append("LWJGL version: ").append(org.lwjgl.Version.getVersion())); hudBuilder.setLength(0);
 
                 this.debugOffsetRight += space;
 
-                drawDebugScreenLineRight(OpenGLHelper.vendor);
-                drawDebugScreenLineRight(OpenGLHelper.renderer);
-                drawDebugScreenLineRight(OpenGLHelper.version);
-                drawDebugScreenLineRight(String.format("OpenGL %s.%s", GL41.glGetInteger(GL41.GL_MAJOR_VERSION), GL41.glGetInteger(GL41.GL_MINOR_VERSION)));
+                drawDebugScreenLineRight(hudTessellater, OpenGLHelper.vendor);
+                drawDebugScreenLineRight(hudTessellater, OpenGLHelper.renderer);
+                drawDebugScreenLineRight(hudTessellater, OpenGLHelper.version);
+                drawDebugScreenLineRight(hudTessellater, hudBuilder.append("OpenGL ").append(GL41.glGetInteger(GL41.GL_MAJOR_VERSION)).append(".").append(GL41.glGetInteger(GL41.GL_MINOR_VERSION))); hudBuilder.setLength(0);
                 long availableVRam = OpenGLHelper.availableVRam();
                 long totalVRam = OpenGLHelper.totalVRam();
                 if (totalVRam != -1 || availableVRam != -1) {
-                    drawDebugScreenLineRight(String.format("Available Video Memory (%sMB) of %sMB", (availableVRam / 1024), (totalVRam / 1024)));
+                    drawDebugScreenLineRight(hudTessellater, hudBuilder.append("Available Video Memory (").append(availableVRam / 1024).append("MB) of ").append(totalVRam / 1024).append("MB")); hudBuilder.setLength(0);
                 }
-                drawDebugScreenLineRight("Resolution: " + this.mc.gameWindow.getWidthPixels() + "x" + this.mc.gameWindow.getHeightPixels());
-                drawDebugScreenLineRight("Render Resolution: " + this.mc.renderer.getRenderWidth() + "x" + this.mc.renderer.getRenderHeight());
+                drawDebugScreenLineRight(hudTessellater, hudBuilder.append("Resolution: ").append(this.mc.gameWindow.getWidthPixels()).append("x").append(this.mc.gameWindow.getHeightPixels())); hudBuilder.setLength(0);
+                drawDebugScreenLineRight(hudTessellater, hudBuilder.append("Render Resolution: ").append(this.mc.renderer.getRenderWidth()).append("x").append(this.mc.renderer.getRenderHeight())); hudBuilder.setLength(0);
 
-                drawDebugScreenLine("Better than Adventure! " + Minecraft.VERSION);
-                drawDebugScreenLine(this.mc.lineDebug);
+                drawDebugScreenLine(hudTessellater, hudBuilder.append("Better than Adventure! ").append(Minecraft.VERSION)); hudBuilder.setLength(0);
+                drawDebugScreenLine(hudTessellater, this.mc.lineDebug);
                 if (this.mc.terrainRenderer instanceof TerrainRendererMultiDraw terrainRenderer) {
 
                     int regionCount = terrainRenderer.regionBuffer.size();
@@ -223,9 +229,9 @@ public class HudIngame extends Gui {
                     int totalEntries = 0;
                     int visibleEntries = 0;
                     for (int i = 0; i < allRegions.size(); i++) {
-                        RenderRegion region = allRegions.get(i);
+                        RenderRegion<TessellatorTerrainImpl.TerrainVertexConfig> region = allRegions.get(i);
                         for (int j = 0; j < region.renderLists.length; j++) {
-                            RenderList renderList = region.renderLists[j];
+                            RenderList<TessellatorTerrainImpl.TerrainVertexConfig> renderList = region.renderLists[j];
                             if (renderList == null) {
                                 continue;
                             }
@@ -234,46 +240,46 @@ public class HudIngame extends Gui {
                         }
                     }
 
-                    drawDebugScreenLine("R: " + regionCount + " D: " + terrainRenderer.getTotalDrawCalls() + " T: " + visibleEntries + "/" + totalEntries + " VBO: " + terrainRenderer.vertexBuffer.entryCount());
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("R: ").append(regionCount).append(" D: ").append(terrainRenderer.getTotalDrawCalls()).append(" T: ").append(visibleEntries).append("/").append(totalEntries).append(" VBO: ").append(terrainRenderer.vertexBuffer.entryCount())); hudBuilder.setLength(0);
 
-                    RenderRegion currentRegion = terrainRenderer.getRenderRegionAtBlockPos(playerX, playerZ);
+                    RenderRegion<TessellatorTerrainImpl.TerrainVertexConfig> currentRegion = terrainRenderer.getRenderRegionAtBlockPos(playerX, playerZ);
                     totalEntries = 0;
                     visibleEntries = 0;
                     for (int j = 0; j < currentRegion.renderLists.length; j++) {
-                        RenderList renderList = currentRegion.renderLists[j];
+                        RenderList<TessellatorTerrainImpl.TerrainVertexConfig> renderList = currentRegion.renderLists[j];
                         if (renderList == null) {
                             continue;
                         }
                         totalEntries += renderList.size();
                         visibleEntries += renderList.visibleEntryCount();
                     }
-                    drawDebugScreenLine("CR: " + currentRegion + " E: " + visibleEntries + "/" + totalEntries);
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("CR: ").append(currentRegion).append(" E: ").append(visibleEntries).append("/").append(totalEntries)); hudBuilder.setLength(0);
 
                 } else {
-                    drawDebugScreenLine(this.mc.getRendererDebugInfo());
+                    drawDebugScreenLine(hudTessellater, this.mc.getRendererDebugInfo());
                 }
-                drawDebugScreenLine(this.mc.getEntityDebugInfoString());
-                drawDebugScreenLine(this.mc.getEntityCountsInfoString());
-                drawDebugScreenLine(this.mc.getChunkProviderInfoString());
+                drawDebugScreenLine(hudTessellater, this.mc.getEntityDebugInfoString());
+                drawDebugScreenLine(hudTessellater, this.mc.getEntityCountsInfoString());
+                drawDebugScreenLine(hudTessellater, this.mc.getChunkProviderInfoString());
 
                 this.debugOffset += space;
                 this.debugOffsetRight += space;
 
                 if (compass) {
-                    drawDebugScreenLine("X: " + this.mc.thePlayer.x);
-                    drawDebugScreenLine("Y: " + this.mc.thePlayer.y);
-                    drawDebugScreenLine("Z: " + this.mc.thePlayer.z);
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("X: ").append(this.mc.thePlayer.x)); hudBuilder.setLength(0);
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("Y: ").append(this.mc.thePlayer.y)); hudBuilder.setLength(0);
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("Z: ").append(this.mc.thePlayer.z)); hudBuilder.setLength(0);
 
                     int chunkX = MathHelper.floor(this.mc.thePlayer.x) >> 4;
                     int chunkZ = MathHelper.floor(this.mc.thePlayer.z) >> 4;
 
-                    drawDebugScreenLine("Chunk: " + chunkX + ", " + chunkZ);
+                    drawDebugScreenLine(hudTessellater, "Chunk: " + chunkX + ", " + chunkZ);
 
-                    int yaw = DynamicTexture.pmod(java.lang.Math.round(this.mc.thePlayer.yRot), 360);
+                    int yaw = Math.floorMod(java.lang.Math.round(this.mc.thePlayer.yRot), 360);
                     int pitch = java.lang.Math.round(this.mc.thePlayer.xRot);
-                    drawDebugScreenLine("Facing: " + yaw + "°, " + pitch + "° (" + I18n.getInstance().translateKey(getFacingDirection(this.mc.thePlayer).translationKey) + ")");
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("Facing: ").append(yaw).append("°, ").append(pitch).append("° (").append(I18n.getInstance().translateKey(getFacingDirection(this.mc.thePlayer).translationKey)).append(")")); hudBuilder.setLength(0);
                 } else {
-                    drawDebugScreenLine("Hold a compass for more information");
+                    drawDebugScreenLine(hudTessellater, "Hold a compass for more information");
                 }
 
                 if (clock) {
@@ -282,20 +288,20 @@ public class HudIngame extends Gui {
                     int playerX = MathHelper.floor(this.mc.thePlayer.x);
                     int playerY = MathHelper.floor(this.mc.thePlayer.y);
                     int playerZ = MathHelper.floor(this.mc.thePlayer.z);
-                    drawDebugScreenLine("Light: Sky: " + this.mc.currentWorld.getSavedLightValue(LightLayer.Sky, playerX, playerY, playerZ) + " Block: " + this.mc.currentWorld.getSavedLightValue(LightLayer.Block, playerX, playerY, playerZ));
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("Light: Sky: ").append(this.mc.currentWorld.getSavedLightValue(LightLayer.Sky, playerX, playerY, playerZ)).append(" Block: ").append(this.mc.currentWorld.getSavedLightValue(LightLayer.Block, playerX, playerY, playerZ))); hudBuilder.setLength(0);
                 }
 
                 this.debugOffset += space;
 
-                drawDebugScreenLine("Entities: " + this.mc.currentWorld.getLoadedEntityList().size());
-                drawDebugScreenLine("Tile Entities: " + this.mc.currentWorld.getLoadedTileEntityList().size());
+                drawDebugScreenLine(hudTessellater, hudBuilder.append("Entities: ").append(this.mc.currentWorld.getLoadedEntityList().size())); hudBuilder.setLength(0);
+                drawDebugScreenLine(hudTessellater, hudBuilder.append("Tile Entities: ").append(this.mc.currentWorld.getLoadedTileEntityList().size())); hudBuilder.setLength(0);
 
                 this.debugOffset += space;
 
                 if (clock) {
-                    drawDebugScreenLine("Time: " + getTimeString(this.mc) + " (Day " + (this.mc.currentWorld.getWorldTime() / Global.DAY_LENGTH_TICKS) + ")");
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("Time: ").append(getTimeString(this.mc)).append(" (Day ").append(this.mc.currentWorld.getWorldTime() / Global.DAY_LENGTH_TICKS).append(")")); hudBuilder.setLength(0);
                 } else {
-                    drawDebugScreenLine("Hold a clock for more information");
+                    drawDebugScreenLine(hudTessellater, "Hold a clock for more information");
                 }
 
                 this.debugOffset += space;
@@ -304,47 +310,47 @@ public class HudIngame extends Gui {
                     Season season = this.mc.currentWorld.getSeasonManager().getCurrentSeason();
                     String seasonString = season != null ? season.getTranslatedName() : "None";
                     Weather weather = this.mc.currentWorld.getCurrentWeather();
-                    String weatherString = weather != null ? stringtranslate.translateKey(weather.getNameLanguageKey()) : "None";
+                    String weatherString = weather != null ? i18n.translateKey(weather.getNameLanguageKey()) : "None";
 
                     int blockX = MathHelper.floor(this.mc.thePlayer.x);
                     int blockY = MathHelper.floor(this.mc.thePlayer.y);
                     int blockZ = MathHelper.floor(this.mc.thePlayer.z);
 
-                    drawDebugScreenLine("Season: " + seasonString);
-                    drawDebugScreenLine("Weather: " + weatherString + " (" + (this.mc.currentWorld.getWeatherManager().getWeatherDuration() / 20) + "s I: " + percentRound(this.mc.currentWorld.getWeatherManager().getWeatherIntensity()) + "% P: " + percentRound(this.mc.currentWorld.getWeatherManager().getWeatherPower()) + "%)");
-                    drawDebugScreenLine("Biome: " + Registries.BIOMES.getKey(this.mc.currentWorld.getBlockBiome(blockX, blockY, blockZ)));
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("Season: ").append(seasonString)); hudBuilder.setLength(0);
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("Weather: ").append(weatherString).append(" (").append(this.mc.currentWorld.getWeatherManager().getWeatherDuration() / 20).append("s I: ").append(percentRound(this.mc.currentWorld.getWeatherManager().getWeatherIntensity())).append("% P: ").append(percentRound(this.mc.currentWorld.getWeatherManager().getWeatherPower())).append("%)")); hudBuilder.setLength(0);
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("Biome: ").append(Registries.BIOMES.getKey(this.mc.currentWorld.getBlockBiome(blockX, blockY, blockZ)))); hudBuilder.setLength(0);
 
                     float temperature = (float) floor100(this.mc.currentWorld.getBlockTemperature(blockX, blockZ));
                     float humidity = (float) floor100(this.mc.currentWorld.getBlockHumidity(blockX, blockZ));
 
-                    drawDebugScreenLine("Temperature: " + temperature + " Humidity: " + humidity);
+                    drawDebugScreenLine(hudTessellater, hudBuilder.append("Temperature: ").append(temperature).append(" Humidity: ").append(humidity)); hudBuilder.setLength(0);
 
                     WindProvider windProvider = this.mc.currentWorld.getWorldType().getWindManager();
                     if (windProvider != null) {
                         float direction = (float) floor100(windProvider.getWindDirection(this.mc.currentWorld, 0.0f, 500.0f, 0.0f));
                         float intensity = (float) floor100(windProvider.getWindIntensity(this.mc.currentWorld, 0.0f, 500.0f, 0.0f));
 
-                        int yaw = DynamicTexture.pmod(java.lang.Math.round((direction * 360.0f) + 270.0f), 360);
-                        drawDebugScreenLine("Wind: " + yaw + "°, " + java.lang.Math.round(intensity * 100.0f) + "%");
+                        int yaw = Math.floorMod(java.lang.Math.round((direction * 360.0f) + 270.0f), 360);
+                        drawDebugScreenLine(hudTessellater, hudBuilder.append("Wind: ").append(yaw).append("°, ").append(Math.round(intensity * 100.0f)).append("%")); hudBuilder.setLength(0);
                     }
                 } else {
-                    drawDebugScreenLine("Hold a rotary calendar for more information");
+                    drawDebugScreenLine(hudTessellater, "Hold a rotary calendar for more information");
                 }
 
                 this.debugOffset += space;
 
-                drawDebugScreenLine("Seed: " + this.mc.currentWorld.getRandomSeed());
+                drawDebugScreenLine(hudTessellater, hudBuilder.append("Seed: ").append(this.mc.currentWorld.getRandomSeed())); hudBuilder.setLength(0);
 
                 this.debugOffset += space;
 
-                drawDebugScreenLine("CTRL + F3: Show Frametimes");
-                drawDebugScreenLine("F3 + Q: Show Keyboard Shortcuts");
+                drawDebugScreenLine(hudTessellater, "CTRL + F3: Show Frametimes");
+                drawDebugScreenLine(hudTessellater, "F3 + Q: Show Keyboard Shortcuts");
 
                 if (this.mc.objectMouseOver instanceof HitResult.Tile hitTile) {
                     this.debugOffset += space;
 
                     Block<?> block = this.mc.currentWorld.getBlockType(hitTile.tilePos);
-                    drawDebugScreenLineRight("Looking at:");
+                    drawDebugScreenLineRight(hudTessellater, "Looking at:");
 
                     String name;
                     int meta = this.mc.currentWorld.getBlockData(hitTile.tilePos);
@@ -356,15 +362,15 @@ public class HudIngame extends Gui {
 
                     String id = block.namespaceId() + " [" + block.id() + ":" + meta + "]";
 
-                    drawDebugScreenLineRight(name);
-                    drawDebugScreenLineRight(block.getLanguageKey(meta));
-                    drawDebugScreenLineRight(id);
+                    drawDebugScreenLineRight(hudTessellater, name);
+                    drawDebugScreenLineRight(hudTessellater, block.getLanguageKey(meta));
+                    drawDebugScreenLineRight(hudTessellater, id);
 
                     if (compass) {
-                        drawDebugScreenLineRight("[" + hitTile.tilePos.x() + ", " + hitTile.tilePos.y() + ", " + hitTile.tilePos.z() + "]");
+                        drawDebugScreenLineRight(hudTessellater, hudBuilder.append("[").append(hitTile.tilePos.x()).append(", ").append(hitTile.tilePos.y()).append(", ").append(hitTile.tilePos.z()).append("]")); hudBuilder.setLength(0);
                     }
 
-                    drawDebugScreenLineRight("Harvest: " + this.mc.thePlayer.canHarvestBlock(block));
+                    drawDebugScreenLineRight(hudTessellater, hudBuilder.append("Harvest: ").append(this.mc.thePlayer.canHarvestBlock(block))); hudBuilder.setLength(0);
 
                     if (clock) {
                         int lightX = hitTile.tilePos.x();
@@ -376,18 +382,27 @@ public class HudIngame extends Gui {
                         lightY += side.offsetY();
                         lightZ += side.offsetZ();
 
-                        drawDebugScreenLineRight("Light: Sky: " + this.mc.currentWorld.getSavedLightValue(LightLayer.Sky, lightX, lightY, lightZ) + " Block: " + this.mc.currentWorld.getSavedLightValue(LightLayer.Block, lightX, lightY, lightZ));
+                        drawDebugScreenLineRight(hudTessellater, hudBuilder.append("Light: Sky: ").append(this.mc.currentWorld.getSavedLightValue(LightLayer.Sky, lightX, lightY, lightZ)).append(" Block: ").append(this.mc.currentWorld.getSavedLightValue(LightLayer.Block, lightX, lightY, lightZ))); hudBuilder.setLength(0);
                     }
 
-                    drawDebugScreenLineRight("Signal: " + this.mc.currentWorld.hasSignal(hitTile.tilePos, hitTile.side));
-                    drawDebugScreenLineRight("Direct signal: " + this.mc.currentWorld.hasDirectSignal(hitTile.tilePos, hitTile.side));
+                    drawDebugScreenLineRight(hudTessellater, hudBuilder.append("Signal: ").append(this.mc.currentWorld.hasSignal(hitTile.tilePos, hitTile.side))); hudBuilder.setLength(0);
+                    drawDebugScreenLineRight(hudTessellater, hudBuilder.append("Direct signal: ").append(this.mc.currentWorld.hasDirectSignal(hitTile.tilePos, hitTile.side))); hudBuilder.setLength(0);
 
                     for (Tag<Block<?>> tag : BlockTags.TAG_LIST) {
                         if (tag.appliesTo(block)) {
-                            drawDebugScreenLineRight(tag.getName());
+                            drawDebugScreenLineRight(hudTessellater, tag.getName());
                         }
                     }
                 }
+
+                GLRenderer.pushFrame();
+                GLRenderer.setShader(Shaders.COLOR);
+                GLRenderer.setColor4f(0.2f, 0.2f, 0.2f, 0.6f);
+                hudTessellater.draw();
+                GLRenderer.popFrame();
+
+                this.fontRenderer.draw(this.zLevel);
+
                 GLRenderer.popFrame();
             }
         }
@@ -400,7 +415,7 @@ public class HudIngame extends Gui {
 
             TessellatorGeneral tessellator = GLRenderer.getTessellator();
 
-            TextureRegistry.worldAtlas.bind(TextureRegistry.worldAtlas.idToLayerMap.get(mc.debugAtlasLayer));
+            TextureRegistry.worldAtlas.bind(TextureRegistry.worldAtlas.idToLayerMap.get(this.mc.debugAtlasLayer));
 
 
             int blockW = TextureRegistry.worldAtlas.getAtlasWidth();
@@ -428,35 +443,25 @@ public class HudIngame extends Gui {
 
     private final int debugLineHeight = 10;
 
-    private void drawDebugScreenLine(final CharSequence string, final boolean right, final int line, final int offset) {
+    private void drawDebugScreenLine(final @NotNull TessellatorGeneral tessellator, final @NotNull CharSequence string, final boolean right, final int line, final int offset) {
         int width = MathHelper.ceil(this.fontRenderer.stringWidthDouble(string));
         int height = this.debugLineHeight;
         int x = right ? (int) ((this.mc.resolution.getScaledWidthScreenCoords() / DEBUG_SCALE) - width - 2) : 2;
         int y = 3 + line * this.debugLineHeight + offset;
 
-        GLRenderer.pushFrame();
-        GLRenderer.setShader(Shaders.COLOR);
-        GLRenderer.setColor4f(0.2f, 0.2f, 0.2f, 0.6f);
-        final TessellatorGeneral t = GLRenderer.getTessellator();
-
-        t.startDrawingQuads();
-        t.drawRectangle(x - 1, y - 1, width + 2, height);
-        t.draw();
-        GLRenderer.popFrame();
-
-//		fontrenderer.drawStringWithShadow(string, x, y, 0xFFFFFF);
-        drawStringNoShadow(this.fontRenderer, string, x, y, 0xFFFFFF);
+        tessellator.drawRectangle(x - 1, y - 1, width + 2, height);
+        this.fontRenderer.render(string, x, y).setColor(0xFFFFFF).call();
     }
 
-    private void drawDebugScreenLine(final CharSequence string) {
-        drawDebugScreenLine(string, false, this.debugLine++, this.debugOffset);
+    private void drawDebugScreenLine(final @NotNull TessellatorGeneral tessellator, final @NotNull CharSequence string) {
+        drawDebugScreenLine(tessellator, string, false, this.debugLine++, this.debugOffset);
     }
 
-    private void drawDebugScreenLineRight(final CharSequence string) {
-        drawDebugScreenLine(string, true, this.debugLineRight++, this.debugOffsetRight);
+    private void drawDebugScreenLineRight(final @NotNull TessellatorGeneral tessellator, final @NotNull CharSequence string) {
+        drawDebugScreenLine(tessellator, string, true, this.debugLineRight++, this.debugOffsetRight);
     }
 
-    private final List<String> playerListScoreStrings = new ArrayList<>();
+//    private final List<String> playerListScoreStrings = new ArrayList<>();
 
     public void drawPlayerList(int screenWidth, int screenHeight) {
         if (!this.mc.isMultiplayerWorld()) return;
@@ -479,13 +484,13 @@ public class HudIngame extends Gui {
         int longestNameWidth = 0;
         int longestScoreWidth = 0;
 
-        this.playerListScoreStrings.clear();
+//        this.playerListScoreStrings.clear();
 
         for (Map.Entry<String, String> a1 : players.entrySet()) {
             longestNameWidth = Math.max(MathHelper.ceil(this.fontRenderer.stringWidthDouble(a1.getKey())), longestNameWidth);
 
             longestScoreWidth = Math.max(MathHelper.ceil(this.fontRenderer.stringWidthDouble(a1.getValue())), longestScoreWidth);
-            this.playerListScoreStrings.add(a1.getValue());
+//            this.playerListScoreStrings.add(a1.getValue());
         }
 
         final int nameScoreSpace = 4;
@@ -599,7 +604,7 @@ public class HudIngame extends Gui {
 
     protected void renderVignette(float intensity, int xSize, int ySize) {
         intensity = MathHelper.clamp(1.0f - intensity, 0.0f, 1.0f);
-        this.prevVignetteBrightness += (double) (intensity - this.prevVignetteBrightness) * 0.01D;
+        this.prevVignetteBrightness += (intensity - this.prevVignetteBrightness) * 0.01f;
         GLRenderer.disableState(State.DEPTH_TEST);
         GLRenderer.setDepthMask(false);
         GLRenderer.setBlendFunc(BlendFactor.ZERO, BlendFactor.ONE_MINUS_SRC_COLOR);
@@ -630,16 +635,16 @@ public class HudIngame extends Gui {
         GLRenderer.setColor4f(1.0F, 1.0F, 1.0F, intensity);
         IconCoordinate portal = BlockModelDispatcher.getInstance().getDispatch(Blocks.getBlock(this.mc.thePlayer.portalID)).getOverlayTexture(this.mc.thePlayer.portalColor.blockMeta << 4 | BlockLogicPortal.MASK_COLOR_SET);
         portal.parentAtlas.bind();
-        float f1 = (float) portal.getIconUMin();
-        float f2 = (float) portal.getIconVMin();
-        float f3 = (float) portal.getIconUMax();
-        float f4 = (float) portal.getIconVMax();
+        float uMin = (float) portal.getIconUMin();
+        float vMin = (float) portal.getIconVMin();
+        float uMax = (float) portal.getIconUMax();
+        float vMax = (float) portal.getIconVMax();
         TessellatorGeneral tessellator = GLRenderer.getTessellator();
         tessellator.startDrawingQuads();
-        tessellator.addVertexWithUV(0.0D, ySize, -90D, f1, f4);
-        tessellator.addVertexWithUV(xSize, ySize, -90D, f3, f4);
-        tessellator.addVertexWithUV(xSize, 0.0D, -90D, f3, f2);
-        tessellator.addVertexWithUV(0.0D, 0.0D, -90D, f1, f2);
+        tessellator.addVertexWithUV(0.0D, ySize, -90D, uMin, vMax);
+        tessellator.addVertexWithUV(xSize, ySize, -90D, uMax, vMax);
+        tessellator.addVertexWithUV(xSize, 0.0D, -90D, uMax, vMin);
+        tessellator.addVertexWithUV(0.0D, 0.0D, -90D, uMin, vMin);
         tessellator.draw();
         GLRenderer.setDepthMask(true);
         GLRenderer.enableState(State.DEPTH_TEST);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentArmorBar.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentArmorBar.java
index 881f9afa0..5cf479a64 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentArmorBar.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentArmorBar.java
@@ -5,19 +5,23 @@ import net.minecraft.client.gui.ScreenHudEditor;
 import net.minecraft.client.gui.hud.HudIngame;
 import net.minecraft.client.gui.hud.component.layout.Layout;
 import net.minecraft.client.option.GameSettings;
+import net.minecraft.client.render.renderer.BlendFactor;
 import net.minecraft.client.render.renderer.GLRenderer;
+import net.minecraft.client.render.renderer.Shaders;
 import net.minecraft.client.render.renderer.State;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.enums.ArmorHiddenState;
 import net.minecraft.core.enums.HumanArmorShape;
-import net.minecraft.core.enums.IArmorShape;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemArmor;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.item.block.ItemBlock;
 import net.minecraft.core.item.material.ArmorMaterial;
+import net.minecraft.core.util.collection.NamespaceID;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.HashMap;
@@ -25,66 +29,26 @@ import java.util.Map;
 import java.util.Random;
 
 public class HudComponentArmorBar extends HudComponentMovable {
+    private final @NotNull Random random = new Random();
+    private final @NotNull StringBuilder queryBuilder = new StringBuilder();
 
-    private final Random random = new Random();
-
-    public record CustomItemData(IArmorShape shape, String id) {}
-
-    public static final Map<IArmorShape, String> SHAPE_MAP = new HashMap<>();
-    public static final Map<ArmorMaterial, String> MATERIAL_MAP = new HashMap<>();
-    public static final Map<Item, CustomItemData> CUSTOM_ITEM_MAP = new HashMap<>();
+    public static final @NotNull Map<@NotNull Item, @NotNull NamespaceID> CUSTOM_ITEM_MAP = new HashMap<>();
+    private static final @NotNull NamespaceID ITEM_HEAD_ID = new NamespaceID("minecraft", "item_generic");
+    private static final @NotNull NamespaceID BLOCK_HEAD_ID = new NamespaceID("minecraft", "block_generic");
+    private static final @NotNull NamespaceID UNKNOWN_ID = new NamespaceID("minecraft", "unknown");
 
     static {
-        SHAPE_MAP.put(HumanArmorShape.HEAD, "helmet");
-        SHAPE_MAP.put(HumanArmorShape.CHEST, "chestplate");
-        SHAPE_MAP.put(HumanArmorShape.LEGS, "leggings");
-        SHAPE_MAP.put(HumanArmorShape.BOOTS, "boots");
-
-        MATERIAL_MAP.put(ArmorMaterial.LEATHER, "leather");
-        MATERIAL_MAP.put(ArmorMaterial.IRON, "iron");
-        MATERIAL_MAP.put(ArmorMaterial.GOLD, "gold");
-        MATERIAL_MAP.put(ArmorMaterial.CHAINMAIL, "chainmail");
-        MATERIAL_MAP.put(ArmorMaterial.DIAMOND, "diamond");
-        MATERIAL_MAP.put(ArmorMaterial.STEEL, "steel");
-
-        CUSTOM_ITEM_MAP.put(Items.ARMOR_BOOTS_ICESKATES, new CustomItemData(HumanArmorShape.BOOTS, "iceskates"));
-        CUSTOM_ITEM_MAP.put(Items.ARMOR_QUIVER, new CustomItemData(HumanArmorShape.CHEST, "quiver"));
-        CUSTOM_ITEM_MAP.put(Items.ARMOR_QUIVER_GOLD, new CustomItemData(HumanArmorShape.CHEST, "quiver_gold"));
-    }
-
-    public enum ArmorState {
-        EMPTY, HALF, FULL, INFINITE;
-
-        public String getRegistry() {
-            return this.name().toLowerCase();
-        }
-
-        public static ArmorState calculate(double currentDurability, double maxDurability) {
-            if (maxDurability <= 0) return INFINITE;
-            if (currentDurability <= 0) return EMPTY;
-
-            double durabilityPercentage = currentDurability / maxDurability;
-
-            if (durabilityPercentage > 0.50) return FULL;
-            return HALF;
-        }
-    }
-
-    private record ArmorIconKey(IArmorShape shape, ArmorState state, @Nullable ArmorMaterial material, boolean isFlipped) {}
-    private record CustomIconKey(IArmorShape shape, ArmorState state, String customId, boolean isFlipped) {}
-
-    private record ArmorPiece(IArmorShape shape, @Nullable ArmorMaterial material, @Nullable String customId, ArmorState state, double currentDurability, double maxDurability) {
-        public boolean isCustom() {
-            return customId != null;
-        }
+        CUSTOM_ITEM_MAP.put(Items.ARMOR_BOOTS_ICESKATES, new NamespaceID("minecraft", "iceskates"));
+        CUSTOM_ITEM_MAP.put(Items.ARMOR_QUIVER, new NamespaceID("minecraft", "quiver"));
+        CUSTOM_ITEM_MAP.put(Items.ARMOR_QUIVER_GOLD,  new NamespaceID("minecraft", "quiver_gold"));
     }
 
-    private final IArmorShape targetShape;
+    private record IconKey(@NotNull ArmorState state, @NotNull NamespaceID id, boolean isFlipped) {}
 
-    private final Map<ArmorIconKey, IconCoordinate> icons = new HashMap<>();
-    private final Map<CustomIconKey, IconCoordinate> customIcons = new HashMap<>();
+    private final Map<IconKey, IconCoordinate> icons = new HashMap<>();
+    private final @NotNull HumanArmorShape targetShape;
 
-    public HudComponentArmorBar(String key, Layout layout, IArmorShape targetShape) {
+    public HudComponentArmorBar(@NotNull String key, @NotNull Layout layout, @NotNull HumanArmorShape targetShape) {
         super(key, 9, 12, layout);
         this.targetShape = targetShape;
     }
@@ -98,8 +62,8 @@ public class HudComponentArmorBar extends HudComponentMovable {
             return 12;
         }
 
-        ArmorPiece piece = getWornArmorPiece();
-        if (piece == null || piece.state() == ArmorState.EMPTY) {
+        ItemStack piece = getWornArmor();
+        if (piece == null || ArmorState.calculate(piece) == ArmorState.EMPTY) {
             return 9;
         }
 
@@ -107,73 +71,67 @@ public class HudComponentArmorBar extends HudComponentMovable {
     }
 
     private boolean isFlipped() {
-        if (this.targetShape == HumanArmorShape.HEAD) return GameSettings.FLIP_HELMET_BAR.value;
-        if (this.targetShape == HumanArmorShape.CHEST) return GameSettings.FLIP_CHESTPLATE_BAR.value;
-        if (this.targetShape == HumanArmorShape.LEGS) return GameSettings.FLIP_LEGGINGS_BAR.value;
-        if (this.targetShape == HumanArmorShape.BOOTS) return GameSettings.FLIP_BOOTS_BAR.value;
-        return false;
+        return switch (this.targetShape) {
+            case HEAD -> GameSettings.FLIP_HELMET_BAR.value;
+            case CHEST -> GameSettings.FLIP_CHESTPLATE_BAR.value;
+            case LEGS -> GameSettings.FLIP_LEGGINGS_BAR.value;
+            case BOOTS -> GameSettings.FLIP_BOOTS_BAR.value;
+        };
     }
 
-    private ArmorHiddenState getHiddenState() {
-        if (this.targetShape == HumanArmorShape.HEAD) return GameSettings.HIDE_HELMET_BAR.value;
-        if (this.targetShape == HumanArmorShape.CHEST) return GameSettings.HIDE_CHESTPLATE_BAR.value;
-        if (this.targetShape == HumanArmorShape.LEGS) return GameSettings.HIDE_LEGGINGS_BAR.value;
-        if (this.targetShape == HumanArmorShape.BOOTS) return GameSettings.HIDE_BOOTS_BAR.value;
-        return ArmorHiddenState.NEVER;
+    private @NotNull ArmorHiddenState getHiddenState() {
+        return switch (this.targetShape) {
+            case HEAD -> GameSettings.HIDE_HELMET_BAR.value;
+            case CHEST -> GameSettings.HIDE_CHESTPLATE_BAR.value;
+            case LEGS -> GameSettings.HIDE_LEGGINGS_BAR.value;
+            case BOOTS -> GameSettings.HIDE_BOOTS_BAR.value;
+        };
     }
 
-    private IconCoordinate getIconForState(ArmorPiece piece, boolean isFlipped) {
-        if (piece.isCustom()) {
-            CustomIconKey key = new CustomIconKey(piece.shape(), piece.state(), piece.customId(), isFlipped);
-            return customIcons.computeIfAbsent(key, this::loadCustomIcon);
+    private @NotNull IconCoordinate getIconForState(@NotNull ArmorState state, @Nullable ArmorMaterial material, @Nullable NamespaceID customId, boolean isFlipped) {
+        NamespaceID id;
+        if (customId != null) {
+            id = customId;
+        } else if (material != null) {
+            id = material.identifier;
         } else {
-            ArmorMaterial fetchMaterial = (piece.state() == ArmorState.EMPTY) ? null : piece.material();
-            ArmorIconKey key = new ArmorIconKey(piece.shape(), piece.state(), fetchMaterial, isFlipped);
-            return icons.computeIfAbsent(key, this::loadArmorIcon);
+            id = UNKNOWN_ID;
         }
+        return this.icons.computeIfAbsent(new IconKey(state, id, isFlipped), this::loadArmorIcon);
     }
 
-    private IconCoordinate loadCustomIcon(CustomIconKey key) {
-        String shapeDir = SHAPE_MAP.getOrDefault(key.shape(), "unknown");
-
-        boolean applyFlip = key.isFlipped() && key.state() == ArmorState.HALF;
-        String stateDir = key.state().getRegistry() + (applyFlip ? "/flipped" : "");
-
-        String path = "minecraft:gui/hud/armor/" + shapeDir + "/" + stateDir + "/" + key.customId();
-        return TextureRegistry.getTexture(path);
-    }
-
-    private IconCoordinate loadArmorIcon(ArmorIconKey key) {
-        String shapeDir = SHAPE_MAP.getOrDefault(key.shape(), "unknown");
-
-        boolean applyFlip = key.isFlipped() && key.state() == ArmorState.HALF;
-        String stateDir = key.state().getRegistry() + (applyFlip ? "/flipped" : "");
-
+    private @NotNull IconCoordinate loadArmorIcon(@NotNull IconKey key) {
+        this.queryBuilder.setLength(0);
         if (key.state() == ArmorState.EMPTY) {
-            String path = "minecraft:gui/hud/armor/" + shapeDir + "/" + stateDir + "/empty";
-            return TextureRegistry.getTexture(path);
+            this.queryBuilder.append("minecraft:gui/hud/armor/").append(getShapeName()).append("/").append("/empty");
         } else {
-            String matDir = MATERIAL_MAP.getOrDefault(key.material(), "unknown");
-            String path = "minecraft:gui/hud/armor/" + shapeDir + "/" + stateDir + "/" + matDir;
-            return TextureRegistry.getTexture(path);
+            boolean applyFlip = key.isFlipped() && key.state() == ArmorState.HALF;
+            this.queryBuilder.append(key.id.namespace()).append(":gui/hud/armor/").append(getShapeName()).append("/").append(key.state().getRegistry());
+            if (applyFlip) this.queryBuilder.append("/flipped");
+            this.queryBuilder.append("/").append(key.id.value());
         }
+        return TextureRegistry.getTexture(this.queryBuilder.toString());
+    }
+
+    private @NotNull String getShapeName() {
+        return switch (this.targetShape) {
+            case HEAD -> "helmet";
+            case CHEST -> "chestplate";
+            case LEGS -> "leggings";
+            case BOOTS -> "boots";
+        };
     }
 
     @Override
     public boolean isVisible() {
-        ArmorHiddenState hiddenState = getHiddenState();
+        if (!GameSettings.IMMERSIVE_MODE.drawHotbar()) return false;
 
-        if (hiddenState == ArmorHiddenState.ALWAYS) {
-            return false;
-        }
-
-        if (!GameSettings.IMMERSIVE_MODE.drawHotbar()) {
-            return false;
-        }
+        ArmorHiddenState hiddenState = getHiddenState();
+        if (hiddenState == ArmorHiddenState.ALWAYS) return false;
 
         if (hiddenState == ArmorHiddenState.WHEN_NOT_WEARING) {
-            ArmorPiece piece = getWornArmorPiece();
-            return piece != null && piece.state() != ArmorState.EMPTY;
+            ItemStack armorStack;
+            return mc.thePlayer != null && (armorStack = mc.thePlayer.inventory.armorItemInSlot(this.targetShape)) != null && ArmorState.calculate(armorStack) != ArmorState.EMPTY;
         }
 
         return true;
@@ -186,10 +144,26 @@ public class HudComponentArmorBar extends HudComponentMovable {
 
     @Override
     public void render(HudIngame hud, int xSizeScreen, int ySizeScreen, float partialTick) {
-        ArmorPiece piece = getWornArmorPiece();
-
-        if (piece == null) {
-            piece = new ArmorPiece(this.targetShape, null, null, ArmorState.EMPTY, 0, 0);
+        ItemStack armorStack = getWornArmor();
+        double currentDurability = 0;
+        double maxDurability = 0;
+        ArmorState state = ArmorState.EMPTY;
+        ArmorMaterial material = null;
+        NamespaceID customId = null;
+        if (armorStack != null) {
+            Item item = armorStack.getItem();
+            maxDurability = armorStack.getMaxDamage();
+            currentDurability = maxDurability > 0 ? maxDurability - armorStack.getItemDamageForDisplay() : 0;
+            if (CUSTOM_ITEM_MAP.containsKey(item)) {
+                customId = CUSTOM_ITEM_MAP.get(item);
+                state = ArmorState.calculate(armorStack);
+            } else if (item instanceof ItemArmor<?> armor) {
+                material = armor.getArmorMaterial();
+                state = ArmorState.calculate(armorStack);
+            } else if (this.targetShape == HumanArmorShape.HEAD) {
+                customId = (item instanceof ItemBlock) ? BLOCK_HEAD_ID : ITEM_HEAD_ID;
+                state = ArmorState.INFINITE;
+            }
         }
 
         int x = this.getLayout().getComponentX(this, xSizeScreen);
@@ -198,7 +172,7 @@ public class HudComponentArmorBar extends HudComponentMovable {
         int iconY = y;
 
         boolean inAcidWarning = mc.thePlayer != null && mc.thePlayer.shouldShowAcidVisualEffects() && mc.thePlayer.getGamemode().hasToolDurability();
-        if (piece.maxDurability() > 0 && ((piece.currentDurability() / piece.maxDurability()) <= 0.15 || inAcidWarning) && piece.state() != ArmorState.EMPTY) {
+        if (maxDurability > 0 && ((currentDurability / maxDurability) <= 0.15 || inAcidWarning) && state != ArmorState.EMPTY) {
             this.random.setSeed(hud.updateCounter * 0x4c627L + (long) this.targetShape.getSlotIndex() * 0x9e3779b9L);
             iconY += this.random.nextInt(2);
         }
@@ -208,10 +182,10 @@ public class HudComponentArmorBar extends HudComponentMovable {
 
         boolean isFlipped = this.isFlipped();
 
-        hud.drawGuiIcon(x, iconY, 9, 9, getIconForState(piece, isFlipped));
-        drawDurabilityBar(hud, x, y, piece.state(), piece.currentDurability(), piece.maxDurability(), 0xFF, isFlipped, inAcidWarning);
-
-        GLRenderer.disableState(State.BLEND);
+        TextureRegistry.guiSpriteAtlas.bind();
+        TessellatorGeneral t = GLRenderer.getTessellator();
+        t.startDrawingQuads(); hud.addGuiIconDouble(t, x, iconY, 9, 9, getIconForState(state, material, customId, isFlipped)); t.draw();
+        drawDurabilityBar(hud, x, y, state, currentDurability, maxDurability, 0xFF, isFlipped, inAcidWarning);
     }
 
     @Override
@@ -222,102 +196,113 @@ public class HudComponentArmorBar extends HudComponentMovable {
         GLRenderer.setColor4f(1.0f, 1.0f, 1.0f, 1.0f);
         renderTranslucency();
 
-        ArmorPiece previewPiece;
         int alpha = isPreviewTranslucent() ? 0x55 : 0xFF;
 
-        if (this.targetShape == HumanArmorShape.HEAD) {
-            previewPiece = new ArmorPiece(this.targetShape, ArmorMaterial.LEATHER, null, ArmorState.HALF, 45, 100);
-        } else if (this.targetShape == HumanArmorShape.CHEST) {
-            previewPiece = new ArmorPiece(this.targetShape, ArmorMaterial.IRON, null, ArmorState.HALF, 35, 100);
-        } else if (this.targetShape == HumanArmorShape.LEGS) {
-            previewPiece = new ArmorPiece(this.targetShape, ArmorMaterial.GOLD, null, ArmorState.HALF, 25, 100);
-        } else {
-            previewPiece = new ArmorPiece(this.targetShape, ArmorMaterial.DIAMOND, null, ArmorState.HALF, 15, 100);
+        ArmorMaterial previewMaterial;
+        int previewDurability;
+        switch (this.targetShape) {
+            case HEAD -> {
+                previewMaterial = ArmorMaterial.LEATHER;
+                previewDurability = 45;
+            }
+            case CHEST -> {
+                previewMaterial = ArmorMaterial.IRON;
+                previewDurability = 35;
+            }
+            case LEGS -> {
+                previewMaterial = ArmorMaterial.GOLD;
+                previewDurability = 25;
+            }
+            default-> {
+                previewMaterial = ArmorMaterial.DIAMOND;
+                previewDurability = 15;
+            }
         }
 
         boolean isFlipped = this.isFlipped();
 
-        gui.drawGuiIcon(x, y, 9, 9, getIconForState(previewPiece, isFlipped));
-        drawDurabilityBar(gui, x, y, previewPiece.state(), previewPiece.currentDurability(), previewPiece.maxDurability(), alpha, isFlipped, false);
-
-        GLRenderer.disableState(State.BLEND);
+        TextureRegistry.guiSpriteAtlas.bind();
+        TessellatorGeneral t = GLRenderer.getTessellator();
+        t.startDrawingQuads(); gui.addGuiIconDouble(t, x, y, 9, 9, getIconForState(ArmorState.HALF, previewMaterial, null, isFlipped)); t.draw();
+        drawDurabilityBar(gui, x, y, ArmorState.HALF, previewDurability, 100, alpha, isFlipped, false);
     }
 
-    private void drawDurabilityBar(Gui gui, int x, int y, ArmorState state, double currentDurability, double maxDurability, int alpha, boolean isFlipped, boolean acidWarning) {
+    private void drawDurabilityBar(@NotNull Gui gui, int x, int y, ArmorState state, double currentDurability, double maxDurability, int alpha, boolean isFlipped, boolean acidWarning) {
+        GLRenderer.enableState(State.BLEND);
+        GLRenderer.setShader(Shaders.COLOR);
+        GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
+
+        TessellatorGeneral tess = GLRenderer.getTessellator();
+        tess.startDrawingQuads();
+
         int barMaxWidth = 9;
         int barY = y + 10;
 
         int a = alpha << 24;
 
-        gui.drawRect(x, barY, x + 9, barY + 2, a);
+        gui.drawRect(tess, x, barY, x + 9, barY + 2, a);
 
         if (state == ArmorState.INFINITE) {
             int magentaColor = (0xFFFF00FF & 0x00FFFFFF) | a;
-            gui.drawRect(x, barY, x + barMaxWidth, barY + 1, magentaColor);
-            return;
-        }
-
-        if (maxDurability <= 0) barMaxWidth = 8;
+            gui.drawRect(tess, x, barY, x + barMaxWidth, barY + 1, magentaColor);
+        } else {
+            if (maxDurability <= 0) barMaxWidth = 8;
 
-        int barWidth = (int) Math.round((currentDurability / maxDurability) * barMaxWidth);
-        int progress = (int) Math.round((currentDurability / maxDurability) * 255D);
+            int barWidth = (int) Math.round((currentDurability / maxDurability) * barMaxWidth);
+            int progress = (int) Math.round((currentDurability / maxDurability) * 255D);
 
-        int colorFG;
-        int colorBG;
-        if (acidWarning) {
-            float t = progress / 255F;
-            colorFG = java.awt.Color.HSBtoRGB(0.11F + t * 0.06F, 1f, 1f);
-            colorBG = java.awt.Color.HSBtoRGB(0.11F, 1f, 0.35f);
-        } else {
-            colorFG = java.awt.Color.HSBtoRGB(progress / 255F / 3F, 1f, 1f);
-            colorBG = ((0xFF - progress) / 4) << 16 | 0x3f00;
-        }
+            int colorFG;
+            int colorBG;
+            if (acidWarning) {
+                float t = progress / 255F;
+                colorFG = java.awt.Color.HSBtoRGB(0.11F + t * 0.06F, 1f, 1f);
+                colorBG = java.awt.Color.HSBtoRGB(0.11F, 1f, 0.35f);
+            } else {
+                colorFG = java.awt.Color.HSBtoRGB(progress / 255F / 3F, 1f, 1f);
+                colorBG = ((0xFF - progress) / 4) << 16 | 0x3f00;
+            }
 
-        colorFG = (colorFG & 0x00FFFFFF) | a;
-        colorBG = (colorBG & 0x00FFFFFF) | a;
+            colorFG = (colorFG & 0x00FFFFFF) | a;
+            colorBG = (colorBG & 0x00FFFFFF) | a;
 
-        gui.drawRect(x, barY, x + barMaxWidth, barY + 1, colorBG);
+            gui.drawRect(tess, x, barY, x + barMaxWidth, barY + 1, colorBG);
 
-        if (barWidth > 0) {
-            if (isFlipped) {
-                int startX = x + barMaxWidth - barWidth;
-                gui.drawRect(startX, barY, startX + barWidth, barY + 1, colorFG);
-            } else {
-                gui.drawRect(x, barY, x + barWidth, barY + 1, colorFG);
+            if (barWidth > 0) {
+                if (isFlipped) {
+                    int startX = x + barMaxWidth - barWidth;
+                    gui.drawRect(tess, startX, barY, startX + barWidth, barY + 1, colorFG);
+                } else {
+                    gui.drawRect(tess, x, barY, x + barWidth, barY + 1, colorFG);
+                }
             }
         }
+
+        tess.draw();
     }
 
-    private @Nullable ArmorPiece getWornArmorPiece() {
+    private @Nullable ItemStack getWornArmor() {
         if (mc.thePlayer == null) return null;
+        return mc.thePlayer.inventory.armorItemInSlot(this.targetShape);
+    }
 
-        for (ItemStack itemStack : mc.thePlayer.inventory.armorInventory) {
-            if (itemStack == null) continue;
-
-            Item item = itemStack.getItem();
+    public enum ArmorState {
+        EMPTY, HALF, FULL, INFINITE;
 
-            if (CUSTOM_ITEM_MAP.containsKey(item)) {
-                CustomItemData data = CUSTOM_ITEM_MAP.get(item);
-                if (data.shape() == this.targetShape) {
-                    double maxDurability = itemStack.getMaxDamage();
-                    double currentDurability = maxDurability > 0 ? maxDurability - itemStack.getItemDamageForDisplay() : 0;
-                    ArmorState state = ArmorState.calculate(currentDurability, maxDurability);
-                    return new ArmorPiece(this.targetShape, null, data.id(), state, currentDurability, maxDurability);
-                }
-            } else if (item instanceof ItemArmor<?> armor) {
-                if (armor.getArmorShape() == this.targetShape) {
-                    ArmorMaterial material = armor.getArmorMaterial();
-                    double maxDurability = itemStack.getMaxDamage();
-                    double currentDurability = maxDurability > 0 ? maxDurability - itemStack.getItemDamageForDisplay() : 0;
-                    ArmorState state = ArmorState.calculate(currentDurability, maxDurability);
-                    return new ArmorPiece(this.targetShape, material, null, state, currentDurability, maxDurability);
-                }
-            } else if (this.targetShape == HumanArmorShape.HEAD) {
-                String customId = (item instanceof ItemBlock) ? "block_generic" : "item_generic";
-                return new ArmorPiece(this.targetShape, null, customId, ArmorState.INFINITE, 0, 0);
-            }
+        public @NotNull String getRegistry() {
+            return this.name().toLowerCase();
         }
 
-        return null;
+        public static @NotNull ArmorState calculate(@NotNull ItemStack armorStack) {
+            int maxDurability = armorStack.getMaxDamage();
+            if (maxDurability <= 0) return INFINITE;
+
+            int currentDurability = maxDurability - armorStack.getItemDamageForDisplay();
+            if (currentDurability <= 0) return EMPTY;
+
+            float durabilityPercentage = (float) currentDurability / maxDurability;
+            if (durabilityPercentage > 0.5f) return FULL;
+
+            return HALF;
+        }
     }
 }
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentHotbar.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentHotbar.java
index 9c5fcec2e..14d94a685 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentHotbar.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentHotbar.java
@@ -11,6 +11,7 @@ import net.minecraft.client.render.item.model.ItemModel;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
 import net.minecraft.client.render.renderer.GLRenderer;
 import net.minecraft.client.render.renderer.State;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Blocks;
@@ -201,23 +202,30 @@ public class HudComponentHotbar extends HudComponentMovable {
         Lighting.disable();
     }
 
-    private void drawOrientedBackgrounds(Gui gui, int x, int y, int selectedHotbar, int currentSlotIndex, boolean isLocked, boolean isVertical) {
+    private void drawOrientedBackgrounds(@NotNull Gui gui, int x, int y, int selectedHotbar, int currentSlotIndex, boolean isLocked, boolean isVertical) {
         IconCoordinate selectorDots = TextureRegistry.getTexture("minecraft:gui/hud/hotbar_selector" + selectedHotbar);
         String selTexture = "minecraft:gui/hud/hotbar_selection" + (isLocked ? "_locked" : "");
 
+        TessellatorGeneral t = GLRenderer.getTessellator();
+        TextureRegistry.guiSpriteAtlas.bind();
+
         //Uses OpenGL matrix rotation to draw the horizontal hotbar vertically
         if (isVertical) {
             GLRenderer.pushFrame();
             GLRenderer.modelM4f().translate(x + 22, y, 0);
             GLRenderer.modelM4f().rotate((float) Math.toRadians(90), 0.0f, 0.0f, 1.0f);
-            gui.drawGuiIcon(5, 0, 182, 22, TextureRegistry.getTexture("minecraft:gui/hud/hotbar"));
-            gui.drawGuiIcon(0, 0, 6, 22, selectorDots);
-            gui.drawGuiIcon(4 + currentSlotIndex * 20, -1, 24, 24, TextureRegistry.getTexture(selTexture));
+            t.startDrawingQuads();
+            gui.addGuiIconDouble(t,5, 0, 182, 22, TextureRegistry.getTexture("minecraft:gui/hud/hotbar"));
+            gui.addGuiIconDouble(t,0, 0, 6, 22, selectorDots);
+            gui.addGuiIconDouble(t,4 + currentSlotIndex * 20, -1, 24, 24, TextureRegistry.getTexture(selTexture));
+            t.draw();
             GLRenderer.popFrame();
         } else {
-            gui.drawGuiIcon(x + 5, y, 182, 22, TextureRegistry.getTexture("minecraft:gui/hud/hotbar"));
-            gui.drawGuiIcon(x, y, 6, 22, selectorDots);
-            gui.drawGuiIcon((x + 4) + currentSlotIndex * 20, y - 1, 24, 24, TextureRegistry.getTexture(selTexture));
+            t.startDrawingQuads();
+            gui.addGuiIconDouble(t,x + 5, y, 182, 22, TextureRegistry.getTexture("minecraft:gui/hud/hotbar"));
+            gui.addGuiIconDouble(t,x, y, 6, 22, selectorDots);
+            gui.addGuiIconDouble(t,(x + 4) + currentSlotIndex * 20, y - 1, 24, 24, TextureRegistry.getTexture(selTexture));
+            t.draw();
         }
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentInfoOverlay.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentInfoOverlay.java
index 65e7dc69a..1dc35b596 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentInfoOverlay.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentInfoOverlay.java
@@ -19,17 +19,20 @@ import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.weather.Weathers;
 import org.jetbrains.annotations.NotNull;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import static net.minecraft.core.util.helper.Utils.floor10;
 
 public class HudComponentInfoOverlay extends HudComponentMovable {
+    public static int MAX_LINES = 16;
 
-    private record RenderLine(String text, int color) {}
+    protected @NotNull StringBuilder @NotNull [] lines = new StringBuilder[MAX_LINES];
+    protected int @NotNull [] colors = new int[MAX_LINES];
+    protected int lineIndex = 0;
 
     public HudComponentInfoOverlay(String key, Layout layout) {
         super(key, 175, 150, layout);
+        for (int i = 0; i < this.lines.length; i++) {
+            this.lines[i] = new StringBuilder();
+        }
     }
 
     @Override
@@ -37,7 +40,14 @@ public class HudComponentInfoOverlay extends HudComponentMovable {
         return GameSettings.IMMERSIVE_MODE.drawOverlays() && !GameSettings.SHOW_DEBUG_SCREEN.value;
     }
 
-    private void drawAlignedString(String text, int boxX, int boxY, int boxWidth, int argb) {
+    private @NotNull StringBuilder addLine(int color) {
+        var builder = this.lines[this.lineIndex]; builder.setLength(0);
+        this.colors[this.lineIndex] = color;
+        this.lineIndex++;
+        return builder;
+    }
+
+    private void drawAlignedString(@NotNull CharSequence text, int boxX, int boxY, int boxWidth, int argb) {
         int textWidth = mc.font.stringWidth(text);
         float xMult = GameSettings.HORIZONTAL_INFO_TEXT_ALIGNMENT.value.multiplier;
         int padding = 2;
@@ -54,6 +64,7 @@ public class HudComponentInfoOverlay extends HudComponentMovable {
 
     @Override
     public void render(HudIngame hud, int xSizeScreen, int ySizeScreen, float partialTick) {
+        mc.font.startDrawingDeferred();
         int x = this.getLayout().getComponentX(this, xSizeScreen);
         int y = this.getLayout().getComponentY(this, ySizeScreen);
 
@@ -76,35 +87,36 @@ public class HudComponentInfoOverlay extends HudComponentMovable {
             }
         }
 
-        List<RenderLine> lines = new ArrayList<>();
+        this.lineIndex = 0;
 
         if (GameSettings.VERSION_IN_OVERLAY.value) {
             int color = (GameSettings.OVERLAY_MODE.value == 2) ? 0xFFFFFF60 : 0xFFFFFFFF;
-            lines.add(new RenderLine("Better than Adventure! " + TextFormatting.WHITE + Global.VERSION, color));
+            addLine(color).append("Better than Adventure! ").append(TextFormatting.WHITE).append(Global.VERSION);
+
         }
 
         if (GameSettings.FPS_IN_OVERLAY.value) {
-            lines.add(new RenderLine(mc.lingDebugFPS, 0xFFFFFFFF));
+            addLine(0xFFFFFFFF).append(mc.lingDebugFPS);
         }
 
         if (compass) {
             if (GameSettings.COORDS_IN_OVERLAY.value) {
                 if (GameSettings.OVERLAY_MODE.value == 0) {
-                    lines.add(new RenderLine("x: " + floor10(mc.thePlayer.x) + " y: " + floor10(mc.thePlayer.y) + " z: " + floor10(mc.thePlayer.z), 0xFFFFFFFF));
+                    addLine(0xFFFFFFFF).append("x: ").append(floor10(mc.thePlayer.x)).append(" y: ").append(floor10(mc.thePlayer.y)).append(" z: ").append(floor10(mc.thePlayer.z));
                 }
                 if (GameSettings.OVERLAY_MODE.value == 1) {
-                    lines.add(new RenderLine("x: " + floor10(mc.thePlayer.x), 0xFFFFFFFF));
-                    lines.add(new RenderLine("y: " + floor10(mc.thePlayer.y), 0xFFFFFFFF));
-                    lines.add(new RenderLine("z: " + floor10(mc.thePlayer.z), 0xFFFFFFFF));
+                    addLine(0xFFFFFFFF).append("x: ").append(floor10(mc.thePlayer.x));
+                    addLine(0xFFFFFFFF).append("y: ").append(floor10(mc.thePlayer.y));
+                    addLine(0xFFFFFFFF).append("z: ").append(floor10(mc.thePlayer.z));
                 }
                 if (GameSettings.OVERLAY_MODE.value == 2) {
-                    lines.add(new RenderLine("x: " + floor10(mc.thePlayer.x), 0xFFFF8080));
-                    lines.add(new RenderLine("y: " + floor10(mc.thePlayer.y), 0xFF80FF80));
-                    lines.add(new RenderLine("z: " + floor10(mc.thePlayer.z), 0xFF8080FF));
+                    addLine(0xFFFF8080).append("x: ").append(floor10(mc.thePlayer.x));
+                    addLine(0xFF80FF80).append("y: ").append(floor10(mc.thePlayer.y));
+                    addLine(0xFF8080FF).append("z: ").append(floor10(mc.thePlayer.z));
                 }
             }
             if (GameSettings.DIRECTION_IN_OVERLAY.value) {
-                lines.add(new RenderLine(I18n.getInstance().translateKey(HudIngame.getFacingDirection(mc.thePlayer).translationKey), 0xFFFFFFFF));
+                addLine(0xFFFFFFFF).append(I18n.getInstance().translateKey(HudIngame.getFacingDirection(mc.thePlayer).translationKey));
             }
         }
 
@@ -112,11 +124,11 @@ public class HudComponentInfoOverlay extends HudComponentMovable {
             if (GameSettings.TIME_IN_OVERLAY.value) {
                 int color = (GameSettings.OVERLAY_MODE.value == 2) ? 0xFFFFFF80 : 0xFFFFFFFF;
                 if (GameSettings.OVERLAY_MODE.value == 0) {
-                    lines.add(new RenderLine(String.format("%s %s %d", HudIngame.getTimeString(mc), I18n.getInstance().translateKey("unit.day"), mc.currentWorld.getWorldTime() / Global.DAY_LENGTH_TICKS), color));
+                    addLine(color).append(HudIngame.getTimeString(mc)).append(" ").append(I18n.getInstance().translateKey("unit.day")).append(" ").append(mc.currentWorld.getWorldTime() / Global.DAY_LENGTH_TICKS);
                 }
                 if (GameSettings.OVERLAY_MODE.value > 0) {
-                    lines.add(new RenderLine(HudIngame.getTimeString(mc), color));
-                    lines.add(new RenderLine(String.format("%s %d", I18n.getInstance().translateKey("unit.day"), mc.currentWorld.getWorldTime() / Global.DAY_LENGTH_TICKS), color));
+                    addLine(color).append(HudIngame.getTimeString(mc));
+                    addLine(color).append(I18n.getInstance().translateKey("unit.day")).append(" ").append(mc.currentWorld.getWorldTime() / Global.DAY_LENGTH_TICKS);
                 }
             }
         }
@@ -125,22 +137,23 @@ public class HudComponentInfoOverlay extends HudComponentMovable {
             if (GameSettings.SEASON_IN_OVERLAY.value) {
                 Season season = mc.currentWorld.getSeasonManager().getCurrentSeason();
                 if (season != null) {
-                    lines.add(new RenderLine(season.getTranslatedName(), GameSettings.OVERLAY_MODE.value == 2 ? 0xFF80FFFF : 0xFFFFFFFF));
+                    addLine(GameSettings.OVERLAY_MODE.value == 2 ? 0xFF80FFFF : 0xFFFFFFFF).append(season.getTranslatedName());
                 }
             }
             if (GameSettings.WEATHER_IN_OVERLAY.value) {
                 Weather weather = mc.currentWorld.getCurrentWeather();
                 if (weather != null && weather != mc.currentWorld.getWorldType().getDefaultWeather()) {
-                    lines.add(new RenderLine(I18n.getInstance().translateKey(weather.getNameLanguageKey()), GameSettings.OVERLAY_MODE.value == 2 ? 0xFFFF80FF : 0xFFFFFFFF));
+                    addLine(GameSettings.OVERLAY_MODE.value == 2 ? 0xFFFF80FF : 0xFFFFFFFF).append(I18n.getInstance().translateKey(weather.getNameLanguageKey()));
                 }
             }
             if (GameSettings.BIOME_IN_OVERLAY.value) {
                 String key = mc.currentWorld.getBlockBiome(new TilePos(mc.thePlayer)).translationKey;
-                lines.add(new RenderLine(I18n.getInstance().translateKey(key), 0xFFFFFFFF));
+                addLine(0xFFFFFFFF).append(I18n.getInstance().translateKey(key));
             }
         }
 
-        drawLines(lines, x, y);
+        drawLines(x, y);
+        mc.font.draw(0);
     }
 
     @Override
@@ -148,16 +161,15 @@ public class HudComponentInfoOverlay extends HudComponentMovable {
         int x = this.getLayout().getComponentX(this, xSizeScreen);
         int y = this.getLayout().getComponentY(this, ySizeScreen);
 
-        List<RenderLine> lines = new ArrayList<>();
+        this.lineIndex = 0;
 
         int versionBaseColor = (GameSettings.OVERLAY_MODE.value == 2) ? 0xFFFFFF60 : 0xFFFFFFFF;
         boolean versionEnabled = GameSettings.VERSION_IN_OVERLAY.value;
 
-        String versionText = "Better than Adventure! " + (versionEnabled ? TextFormatting.WHITE : "") + Global.VERSION;
-        lines.add(new RenderLine(versionText, getPreviewColor(versionBaseColor, versionEnabled)));
+        addLine(getPreviewColor(versionBaseColor, versionEnabled)).append("Better than Adventure! ").append(versionEnabled ? TextFormatting.WHITE : "").append(Global.VERSION);
 
         boolean fpsEnabled = GameSettings.FPS_IN_OVERLAY.value;
-        lines.add(new RenderLine("127 fps", getPreviewColor(0xFFFFFFFF, fpsEnabled)));
+        addLine(getPreviewColor(0xFFFFFFFF, fpsEnabled)).append("127 fps");
 
         final double px = 372.853;
         final double py = 64.355;
@@ -165,60 +177,59 @@ public class HudComponentInfoOverlay extends HudComponentMovable {
         boolean coordsEnabled = GameSettings.COORDS_IN_OVERLAY.value;
 
         if (GameSettings.OVERLAY_MODE.value == 0) {
-            lines.add(new RenderLine("x: " + floor10(px) + " y: " + floor10(py) + " z: " + floor10(pz), getPreviewColor(0xFFFFFFFF, coordsEnabled)));
+            addLine(getPreviewColor(0xFFFFFFFF, coordsEnabled)).append("x: ").append(floor10(px)).append(" y: ").append(floor10(py)).append(" z: ").append(floor10(pz));
         } else if (GameSettings.OVERLAY_MODE.value == 1) {
-            lines.add(new RenderLine("x: " + floor10(px), getPreviewColor(0xFFFFFFFF, coordsEnabled)));
-            lines.add(new RenderLine("y: " + floor10(py), getPreviewColor(0xFFFFFFFF, coordsEnabled)));
-            lines.add(new RenderLine("z: " + floor10(pz), getPreviewColor(0xFFFFFFFF, coordsEnabled)));
+            addLine(getPreviewColor(0xFFFFFFFF, coordsEnabled)).append("x: ").append(floor10(px));
+            addLine(getPreviewColor(0xFFFFFFFF, coordsEnabled)).append("y: ").append(floor10(py));
+            addLine(getPreviewColor(0xFFFFFFFF, coordsEnabled)).append("z: ").append(floor10(pz));
         } else if (GameSettings.OVERLAY_MODE.value == 2) {
-            lines.add(new RenderLine("x: " + floor10(px), getPreviewColor(0xFFFF8080, coordsEnabled)));
-            lines.add(new RenderLine("y: " + floor10(py), getPreviewColor(0xFF80FF80, coordsEnabled)));
-            lines.add(new RenderLine("z: " + floor10(pz), getPreviewColor(0xFF8080FF, coordsEnabled)));
+            addLine(getPreviewColor(0xFFFF8080, coordsEnabled)).append("x: ").append(floor10(px));
+            addLine(getPreviewColor(0xFF80FF80, coordsEnabled)).append("y: ").append(floor10(py));
+            addLine(getPreviewColor(0xFF8080FF, coordsEnabled)).append("z: ").append(floor10(pz));
         }
 
         boolean dirEnabled = GameSettings.DIRECTION_IN_OVERLAY.value;
-        lines.add(new RenderLine(I18n.getInstance().translateKey(Direction.NORTH.translationKey), getPreviewColor(0xFFFFFFFF, dirEnabled)));
+        addLine(getPreviewColor(0xFFFFFFFF, dirEnabled)).append(I18n.getInstance().translateKey(Direction.NORTH.translationKey));
 
         int clockColor = (GameSettings.OVERLAY_MODE.value == 2) ? 0xFFFFFF80 : 0xFFFFFFFF;
         boolean timeEnabled = GameSettings.TIME_IN_OVERLAY.value;
 
         if (GameSettings.OVERLAY_MODE.value == 0) {
-            lines.add(new RenderLine(String.format("%s %s %d", "8:32", I18n.getInstance().translateKey("unit.day"), 500), getPreviewColor(clockColor, timeEnabled)));
+            addLine(getPreviewColor(clockColor, timeEnabled)).append("8:32 ").append(I18n.getInstance().translateKey("unit.day")).append(" ").append(500);
         } else if (GameSettings.OVERLAY_MODE.value > 0) {
-            lines.add(new RenderLine("8:32", getPreviewColor(clockColor, timeEnabled)));
-            lines.add(new RenderLine(String.format("%s %d", I18n.getInstance().translateKey("unit.day"), 500), getPreviewColor(clockColor, timeEnabled)));
+            addLine(getPreviewColor(clockColor, timeEnabled)).append("8:32");
+            addLine(getPreviewColor(clockColor, timeEnabled)).append(I18n.getInstance().translateKey("unit.day")).append(" ").append(500);
         }
 
         Season season = Seasons.OVERWORLD_SUMMER;
         boolean seasonEnabled = GameSettings.SEASON_IN_OVERLAY.value;
-        lines.add(new RenderLine(season.getTranslatedName(), getPreviewColor(GameSettings.OVERLAY_MODE.value == 2 ? 0xFF80FFFF : 0xFFFFFFFF, seasonEnabled)));
+        addLine(getPreviewColor(GameSettings.OVERLAY_MODE.value == 2 ? 0xFF80FFFF : 0xFFFFFFFF, seasonEnabled)).append(season.getTranslatedName());
 
         Weather weather = Weathers.OVERWORLD_FOG;
         boolean weatherEnabled = GameSettings.WEATHER_IN_OVERLAY.value;
-        lines.add(new RenderLine(I18n.getInstance().translateKey(weather.getNameLanguageKey()), getPreviewColor(GameSettings.OVERLAY_MODE.value == 2 ? 0xFFFF80FF : 0xFFFFFFFF, weatherEnabled)));
+        addLine(getPreviewColor(GameSettings.OVERLAY_MODE.value == 2 ? 0xFFFF80FF : 0xFFFFFFFF, weatherEnabled)).append(I18n.getInstance().translateKey(weather.getNameLanguageKey()));
 
         String biomeKey = Biomes.OVERWORLD_GRASSLANDS.translationKey;
         boolean biomeEnabled = GameSettings.BIOME_IN_OVERLAY.value;
-        lines.add(new RenderLine(I18n.getInstance().translateKey(biomeKey), getPreviewColor(0xFFFFFFFF, biomeEnabled)));
+        addLine(getPreviewColor(0xFFFFFFFF, biomeEnabled)).append(I18n.getInstance().translateKey(biomeKey));
 
-        drawLines(lines, x, y);
+        drawLines(x, y);
     }
 
-    private void drawLines(@NotNull List<RenderLine> lines, int x, int y) {
-        if (lines.isEmpty()) return;
+    private void drawLines(int x, int y) {
+        final int size = this.lineIndex;
 
-        int lineHeight = 10;
-        int totalHeight = lines.size() * lineHeight;
+        final int lineHeight = 10;
+        final int totalHeight = size * lineHeight;
 
-        float yMult = GameSettings.VERTICAL_INFO_TEXT_ALIGNMENT.value.multiplier;
+        final float yMult = GameSettings.VERTICAL_INFO_TEXT_ALIGNMENT.value.multiplier;
 
         int padding = 2;
         int startY = y + padding + (int) ((this.getBaseYSize() - (padding * 2) - totalHeight) * yMult);
 
-        for (int i = 0; i < lines.size(); i++) {
-            RenderLine line = lines.get(i);
+        for (int i = 0; i < size; i++) {
             int currentY = startY + (i * lineHeight);
-            drawAlignedString(line.text, x, currentY, this.getBaseXSize(), line.color);
+            drawAlignedString(this.lines[i], x, currentY, this.getBaseXSize(), this.colors[i]);
         }
     }
 }
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentLog.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentLog.java
index ae1b12c06..913cdd37c 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentLog.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentLog.java
@@ -157,12 +157,14 @@ public class HudComponentLog extends HudComponentMovable {
         int totalHeight = lines.length * LINE_HEIGHT;
         int startY = y + PADDING + (int) ((this.getBaseYSize() - (PADDING * 2) - totalHeight) * yMult);
 
+        sr.startDrawingDeferred();
         for (int i = 0; i < lines.length; i++) {
             String line = lines[i];
             int currentY = startY + (i * LINE_HEIGHT);
             int color = 0x00_FF_FF_FF + ((int) (opacities[i] * 0xFF) << 24);
             drawAlignedString(sr, line, x, currentY, this.getBaseXSize(), color);
         }
+        sr.draw(0);
         GLRenderer.disableState(State.BLEND);
     }
 }
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 bc100ff7b..1481a19ca 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
@@ -380,6 +380,7 @@ public abstract class OptionsPages {
                 .withComponent(new KeyBindingComponent(GameSettings.KEY_SMOOTH_LIGHTING))
                 .withComponent(new KeyBindingComponent(GameSettings.KEY_RELEASE_CURSOR))
                 .withComponent(new KeyBindingComponent(GameSettings.KEY_LOAD_CHUNKS_QUICKLY))
+                .withComponent(new KeyBindingComponent(GameSettings.KEY_TOGGLE_FRAME_LIMIT))
             )
             .withComponent(new OptionsCategory("gui.options.page.debug.category.utility")
                 .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.model_viewer", () -> {
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 f10ea0fbc..e8445791d 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
@@ -648,6 +648,7 @@ public final class GameSettings {
     public static final @NotNull KeyBinding KEY_TOGGLE_TEXTURE_ATLAS = register(new KeyBinding("key.debug.textureAtlas"));
     public static final @NotNull KeyBinding KEY_SHIFT_TEXTURE_ATLAS_LAYER = register(new KeyBinding("key.debug.textureAtlasLayer"));
     public static final @NotNull KeyBinding KEY_LOAD_CHUNKS_QUICKLY = register(new KeyBinding("key.debug.loadChunksQuickly"));
+    public static final @NotNull KeyBinding KEY_TOGGLE_FRAME_LIMIT = register(new KeyBinding("key.debug.toggleFrameLimit"));
 
     static {
         DEBUG_KEYS.add(KEY_SHOW_SHORTCUTS);
diff --git a/game/client/src/main/java/net/minecraft/client/option/OptionFont.java b/game/client/src/main/java/net/minecraft/client/option/OptionFont.java
index 89fc679e5..4b4af2dbe 100644
--- a/game/client/src/main/java/net/minecraft/client/option/OptionFont.java
+++ b/game/client/src/main/java/net/minecraft/client/option/OptionFont.java
@@ -24,7 +24,7 @@ public class OptionFont extends OptionToggleable<@NotNull Font> implements Toggl
 
     @Override
     public void toggle(final int delta) {
-        this.value = Fonts.fontAtIndex(DynamicTexture.pmod(getValueIndex() + delta, size()));
+        this.value = Fonts.fontAtIndex(Math.floorMod(getValueIndex() + delta, size()));
     }
 
     @Override
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 37242801f..fb94ec95b 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
@@ -20,7 +20,7 @@ public abstract class OptionToggleable<E> extends Option<E> implements Toggleabl
 	}
 	
 	public void toggle(int delta) {
-		this.value = this.values[DynamicTexture.pmod(getValueIndex() + delta, this.values.length)];
+		this.value = this.values[Math.floorMod(getValueIndex() + delta, this.values.length)];
 	}
 	
 	public int getValueIndex() {
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
index 6cf41251b..3169e22b3 100644
--- a/game/client/src/main/java/net/minecraft/client/option/OptionTooltip.java
+++ b/game/client/src/main/java/net/minecraft/client/option/OptionTooltip.java
@@ -23,7 +23,7 @@ public class OptionTooltip extends OptionToggleable<String> implements Toggleabl
 
     @Override
     public void toggle(final int delta) {
-        this.value = TooltipElement.stylesIdList.get(DynamicTexture.pmod(getValueIndex() + delta, size()));
+        this.value = TooltipElement.stylesIdList.get(Math.floorMod(getValueIndex() + delta, size()));
     }
 
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/render/FogManager.java b/game/client/src/main/java/net/minecraft/client/render/FogManager.java
index f18de7261..06a32b2fc 100644
--- a/game/client/src/main/java/net/minecraft/client/render/FogManager.java
+++ b/game/client/src/main/java/net/minecraft/client/render/FogManager.java
@@ -241,14 +241,13 @@ public class FogManager {
             return this;
         }
 
-        public @NotNull FogState copy() {
-            FogState newState = new FogState();
-            newState.fogColor.set(this.fogColor);
-            newState.fogMode = this.fogMode;
-            newState.fogStart = this.fogStart;
-            newState.fogEnd = this.fogEnd;
-            newState.fogDensity = this.fogDensity;
-            return newState;
+        public @NotNull FogState copy(@NotNull FogState dest) {
+            dest.fogColor.set(this.fogColor);
+            dest.fogMode = this.fogMode;
+            dest.fogStart = this.fogStart;
+            dest.fogEnd = this.fogEnd;
+            dest.fogDensity = this.fogDensity;
+            return dest;
         }
 
         public enum Mode {
diff --git a/game/client/src/main/java/net/minecraft/client/render/culling/CameraFrustum.java b/game/client/src/main/java/net/minecraft/client/render/culling/CameraFrustum.java
index ee5c2aeff..4f6af8aef 100644
--- a/game/client/src/main/java/net/minecraft/client/render/culling/CameraFrustum.java
+++ b/game/client/src/main/java/net/minecraft/client/render/culling/CameraFrustum.java
@@ -8,7 +8,7 @@ import org.joml.FrustumIntersection;
 import org.joml.Matrix4f;
 import org.joml.primitives.AABBdc;
 
-public class CameraFrustum {
+public final class CameraFrustum {
     private final @NotNull ICamera camera;
     private static final @NotNull FrustumIntersection frustum = new FrustumIntersection();
     private static final @NotNull Matrix4f matrix4f = new Matrix4f();
@@ -40,7 +40,17 @@ public class CameraFrustum {
 
     public boolean isVisible(@NotNull AABBdc aabb, float partialTick) {
         if (GameSettings.FRUSTUM_CULLING.value) {
-            return cubeInFrustum(aabb, partialTick);
+            final double x = this.camera.getX(partialTick);
+            final double y = this.camera.getY(partialTick);
+            final double z = this.camera.getZ(partialTick);
+            return frustum.testAab(
+                (float) (aabb.minX() - x),
+                (float) (aabb.minY() - y),
+                (float) (aabb.minZ() - z),
+                (float) (aabb.maxX() - x),
+                (float) (aabb.maxY() - y),
+                (float) (aabb.maxZ() - z)
+            );
         } else {
             return true;
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTexture.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTexture.java
index 489609947..78910d053 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTexture.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTexture.java
@@ -44,11 +44,6 @@ public abstract class DynamicTexture {
         return this.imageData[layer];
     }
 
-	public static int pmod(int a, int b) {
-		while(a < 0) a += b;
-		return a % b;
-	}
-
 	public static void putPixel(byte[] array, int i, int color) {
 		int r = (color >> 16) & 0xFF;
 		int g = (color >>  8) & 0xFF;
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureLavaFlowing.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureLavaFlowing.java
index fe3177505..8118f9267 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureLavaFlowing.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureLavaFlowing.java
@@ -4,6 +4,8 @@ import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.util.helper.MathHelper;
 import org.jetbrains.annotations.NotNull;
 
+import static java.lang.Math.floorMod;
+
 public class DynamicTextureLavaFlowing extends DynamicTexture {
 
 	private float[] arr1;
@@ -47,21 +49,21 @@ public class DynamicTextureLavaFlowing extends DynamicTexture {
 
 				for (_x = x - 1; _x <= x + 1; ++_x) {
 					for (_y = y - 1; _y <= y + 1; ++_y) {
-						var8 = pmod(_x + var4, this.targetTexture.width);
-						var9 = pmod(_y + var5, this.targetTexture.height);
+						var8 = floorMod(_x + var4, this.targetTexture.width);
+						var9 = floorMod(_y + var5, this.targetTexture.height);
 						var3 += this.arr1[var8 + var9 * this.targetTexture.width];
 					}
 				}
 
 				this.arr2[x + y * this.targetTexture.width] = var3 / 10.0F
-						+ (this.arr3[(pmod(x, this.targetTexture.width))
-						+ (pmod(y, this.targetTexture.height)) * this.targetTexture.width]
-						+ this.arr3[(pmod(x + 1, this.targetTexture.width))
-						+ (pmod(y, this.targetTexture.height)) * this.targetTexture.width]
-						+ this.arr3[(pmod(x + 1, this.targetTexture.width))
-						+ (pmod(y + 1, this.targetTexture.height)) * this.targetTexture.width]
-						+ this.arr3[(pmod(x, this.targetTexture.width))
-						+ (pmod(y + 1, this.targetTexture.height)) * this.targetTexture.width]) / 4.0F * 0.8F;
+						+ (this.arr3[(floorMod(x, this.targetTexture.width))
+						+ (floorMod(y, this.targetTexture.height)) * this.targetTexture.width]
+						+ this.arr3[(floorMod(x + 1, this.targetTexture.width))
+						+ (floorMod(y, this.targetTexture.height)) * this.targetTexture.width]
+						+ this.arr3[(floorMod(x + 1, this.targetTexture.width))
+						+ (floorMod(y + 1, this.targetTexture.height)) * this.targetTexture.width]
+						+ this.arr3[(floorMod(x, this.targetTexture.width))
+						+ (floorMod(y + 1, this.targetTexture.height)) * this.targetTexture.width]) / 4.0F * 0.8F;
 				this.arr3[x + y * this.targetTexture.width] += this.arr4[x + y * this.targetTexture.width] * 0.01F;
 				if (this.arr3[x + y * this.targetTexture.width] < 0.0F) {
 					this.arr3[x + y * this.targetTexture.width] = 0.0F;
@@ -79,7 +81,7 @@ public class DynamicTextureLavaFlowing extends DynamicTexture {
 		this.arr1 = var11;
 
 		for (int i = 0; i < this.targetTexture.getArea(); ++i) {
-			var3 = this.arr1[pmod(i - this.ticks / 3 * this.targetTexture.width, this.targetTexture.getArea())] * 2.0F;
+			var3 = this.arr1[floorMod(i - this.ticks / 3 * this.targetTexture.width, this.targetTexture.getArea())] * 2.0F;
 			if (var3 > 1.0F) {
 				var3 = 1.0F;
 			}
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureLavaStill.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureLavaStill.java
index 256db012f..0dc0e7182 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureLavaStill.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureLavaStill.java
@@ -4,6 +4,8 @@ import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.util.helper.MathHelper;
 import org.jetbrains.annotations.NotNull;
 
+import static java.lang.Math.floorMod;
+
 public class DynamicTextureLavaStill extends DynamicTexture {
 
 	private float[] arr1;
@@ -42,21 +44,21 @@ public class DynamicTextureLavaStill extends DynamicTexture {
 
 				for (g = i - 1; g <= i + 1; ++g) {
 					for (b = j - 1; b <= j + 1; ++b) {
-						var8 = pmod(g + x2, this.targetTexture.width);
-						var9 = pmod(b + y2, this.targetTexture.height);
+						var8 = floorMod(g + x2, this.targetTexture.width);
+						var9 = floorMod(b + y2, this.targetTexture.height);
 						var3 += this.arr1[var8 + var9 * this.targetTexture.width];
 					}
 				}
 
 				this.arr2[i + j * this.targetTexture.width] = var3 / 10.0F
-						+ (this.arr3[(pmod(i, this.targetTexture.width))
-						+ (pmod(j, this.targetTexture.height)) * this.targetTexture.width]
-						+ this.arr3[(pmod(i + 1, this.targetTexture.width))
-						+ (pmod(j, this.targetTexture.height)) * this.targetTexture.width]
-						+ this.arr3[(pmod(i + 1, this.targetTexture.width))
-						+ (pmod(j + 1, this.targetTexture.height)) * this.targetTexture.width]
-						+ this.arr3[(pmod(i, this.targetTexture.width))
-						+ (pmod(j + 1, this.targetTexture.height)) * this.targetTexture.width]) / 4.0F * 0.8F;
+						+ (this.arr3[(floorMod(i, this.targetTexture.width))
+						+ (floorMod(j, this.targetTexture.height)) * this.targetTexture.width]
+						+ this.arr3[(floorMod(i + 1, this.targetTexture.width))
+						+ (floorMod(j, this.targetTexture.height)) * this.targetTexture.width]
+						+ this.arr3[(floorMod(i + 1, this.targetTexture.width))
+						+ (floorMod(j + 1, this.targetTexture.height)) * this.targetTexture.width]
+						+ this.arr3[(floorMod(i, this.targetTexture.width))
+						+ (floorMod(j + 1, this.targetTexture.height)) * this.targetTexture.width]) / 4.0F * 0.8F;
 				
 				this.arr3[i + j * this.targetTexture.width] += this.arr4[i + j * this.targetTexture.width] * 0.01F;
 				if (this.arr3[i + j * this.targetTexture.width] < 0.0F) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureWaterFlow.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureWaterFlow.java
index f6bde9165..be34c4c97 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureWaterFlow.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureWaterFlow.java
@@ -7,6 +7,8 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.type.tag.WorldTypeTags;
 import org.jetbrains.annotations.NotNull;
 
+import static java.lang.Math.floorMod;
+
 public class DynamicTextureWaterFlow extends DynamicTexture {
 	
 	private final Minecraft mc = Minecraft.getMinecraft();
@@ -40,8 +42,8 @@ public class DynamicTextureWaterFlow extends DynamicTexture {
 				float pow = 0.0F;
 
 				for (int k = y - 2; k <= y; ++k) {
-					int xi = pmod(x, this.targetTexture.width);
-					int yi = pmod(k, this.targetTexture.height);
+					int xi = floorMod(x, this.targetTexture.width);
+					int yi = floorMod(k, this.targetTexture.height);
 					pow += this.current[xi + yi * this.targetTexture.width];
 				}
 
@@ -69,7 +71,7 @@ public class DynamicTextureWaterFlow extends DynamicTexture {
 
         byte[] imageData = getImageData(this.layerColor);
 		for (int i = 0; i < this.targetTexture.getArea(); ++i) {
-			float pow = this.current[pmod(i - this.ticks * this.targetTexture.width, this.targetTexture.getArea())];
+			float pow = this.current[floorMod(i - this.ticks * this.targetTexture.width, this.targetTexture.getArea())];
 			pow = MathHelper.clamp(pow, 0.0f, 1.0f);
 			float pp = pow * pow;
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureWaterStill.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureWaterStill.java
index fd38d5742..04769b748 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureWaterStill.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureWaterStill.java
@@ -11,6 +11,8 @@ import org.jetbrains.annotations.Nullable;
 
 import java.awt.image.BufferedImage;
 
+import static java.lang.Math.floorMod;
+
 public class DynamicTextureWaterStill extends DynamicTexture {
 	
 	private final Minecraft mc = Minecraft.getMinecraft();
@@ -53,8 +55,8 @@ public class DynamicTextureWaterStill extends DynamicTexture {
 				float pow = 0.0F;
 
 				for (int xx = x - 1; xx <= x + 1; ++xx) {
-					final int xi = pmod(xx, this.targetTexture.width);
-					final int yi = pmod(y, this.targetTexture.height);
+					final int xi = floorMod(xx, this.targetTexture.width);
+					final int yi = floorMod(y, this.targetTexture.height);
 					pow += this.current[xi + yi * this.targetTexture.width];
 				}
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererArrow.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererArrow.java
index c394a3896..824facdb1 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererArrow.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererArrow.java
@@ -19,6 +19,8 @@ public class EntityRendererArrow extends EntityRenderer<ProjectileArrow> {
         }
 
         bindTexture("/assets/minecraft/textures/entity/arrows.png");
+        float imgWidth = 16f;
+        float imgHeight = 64f;
         GLRenderer.pushFrame();
         GLRenderer.modelM4f().translate((float) x, (float) y, (float) z);
 
@@ -27,14 +29,14 @@ public class EntityRendererArrow extends EntityRenderer<ProjectileArrow> {
 
         int arrowType = arrow.getArrowType();
 
-        float bodyMinU = 0F / 32F;
-        float bodyMaxU = 16F / 32F;
-        float bodyMinV = (float) (arrowType * 10) / 32F;
-        float bodyMaxV = (float) (5 + arrowType * 10) / 32F;
-        float tailMinU = 0F / 32F;
-        float tailMaxU = 5F / 32F;
-        float tailMinV = (float) (5 + arrowType * 10) / 32F;
-        float tailMaxV = (float) (10 + arrowType * 10) / 32F;
+        float bodyMinU = 0F / imgWidth;
+        float bodyMaxU = 16F / imgWidth;
+        float bodyMinV = (float) (arrowType * 10) / imgHeight;
+        float bodyMaxV = (float) (5 + arrowType * 10) / imgHeight;
+        float tailMinU = 0F / imgWidth;
+        float tailMaxU = 5F / imgWidth;
+        float tailMinV = (float) (5 + arrowType * 10) / imgHeight;
+        float tailMaxV = (float) (10 + arrowType * 10) / imgHeight;
         float scale = 9F / 160F;
 
         float shakeAmount = (float) arrow.shake - partialTick;
diff --git a/game/client/src/main/java/net/minecraft/client/render/font/FontRenderer.java b/game/client/src/main/java/net/minecraft/client/render/font/FontRenderer.java
index 08c4e334a..0288e31b3 100644
--- a/game/client/src/main/java/net/minecraft/client/render/font/FontRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/font/FontRenderer.java
@@ -1,5 +1,6 @@
 package net.minecraft.client.render.font;
 
+import net.minecraft.client.render.tessellator.TessellatorFont;
 import net.minecraft.core.util.helper.MathHelper;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -176,4 +177,8 @@ public abstract class FontRenderer {
     public void init() {
 
     }
+
+    public abstract void startDrawingDeferred();
+    public abstract void draw(double z);
+    public abstract @NotNull TessellatorFont.FontRenderBuffer record(int vao, int vbo);
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/font/FontRendererDefault.java b/game/client/src/main/java/net/minecraft/client/render/font/FontRendererDefault.java
index 67cf599d0..1033abc2b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/font/FontRendererDefault.java
+++ b/game/client/src/main/java/net/minecraft/client/render/font/FontRendererDefault.java
@@ -24,6 +24,7 @@ public class FontRendererDefault extends FontRenderer {
     protected final long @NotNull [] configStack = new long[32];
     protected byte stackIndex = 0;
     protected long currentConfig = 0;
+    protected boolean drawingDeferred = false;
 
     protected int currentTex = -1;
     protected final Random random;
@@ -50,6 +51,32 @@ public class FontRendererDefault extends FontRenderer {
         this.tessellatorFont = new TessellatorFont("FontRenderDefault Base Tessellator", 0x40000);
     }
 
+    @Override
+    public void startDrawingDeferred() {
+        if (this.drawingDeferred) throw new IllegalStateException("Already drawing deferred!");
+        this.drawingDeferred = true;
+        this.tessellatorFont.startDrawing();
+    }
+
+    @Override
+    public void draw(double z) {
+        GLRenderer.pushFrame();
+        GLRenderer.enableState(State.BLEND);
+        GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
+        GLRenderer.globalSetUniforms(Shaders.FONT);
+        GL41.glUniform1f(Shaders.FONT.getUniform("uZ"), (float) z);
+        this.tessellatorFont.draw();
+
+        GLRenderer.popFrame();
+        this.drawingDeferred = false;
+    }
+
+    @Override
+    public @NotNull TessellatorFont.FontRenderBuffer record(int vao, int vbo) {
+        this.drawingDeferred = false;
+        return this.tessellatorFont.record(vao, vbo);
+    }
+
     private final StringBuilder renderStringInternal_colorValue = new StringBuilder();
     protected void renderStringInternal(@NotNull final Font font, final @NotNull CharSequence chars, final double x, final double y, final double z, final boolean shadow, final long baseConfig, final double @Nullable [] xPosBuffer, final double @Nullable [] yPosBuffer, final long @Nullable [] configBuffer) {
         double currX = x;
@@ -175,11 +202,6 @@ public class FontRendererDefault extends FontRenderer {
         return this.tessellatorFont;
     }
 
-    public void renderStringRaw(@NotNull final Font font, final @NotNull CharSequence chars, final double x, final double y, final double z, final boolean shadow, final long baseConfig) {
-        this.currentConfig = baseConfig;
-        renderStringInternal(font, chars, x, y, z, shadow, baseConfig, null, null, null);
-    }
-
     protected double renderCharInternal(@NotNull final Font font, @NotNull final TessellatorFont tessellator, final char c, final double x, final double y, final double z, boolean shadow) {
         tessellator.setShadow(shadow);
         tessellator.setConfig(this.currentConfig);
@@ -201,21 +223,10 @@ public class FontRendererDefault extends FontRenderer {
         this.currentTex = -1;
         this.currentConfig = baseConfig;
         this.stackIndex = 0;
-        GLRenderer.pushFrame();
-        GLRenderer.enableState(State.BLEND);
-        GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
-        GLRenderer.globalSetUniforms(Shaders.FONT);
-        Shaders.FONT.bind();
-        GL41.glUniform1f(Shaders.FONT.getUniform("uZ"), (float) z);
-
-        this.tessellatorFont.startDrawing();
 
+        if (!this.drawingDeferred) this.tessellatorFont.startDrawing();
         renderStringInternal(font, chars, x, y, z, shadow, baseConfig, xPosBuffer, yPosBuffer, configBuffer);
-
-        Shaders.FONT.bind();
-        this.tessellatorFont.draw();
-
-        GLRenderer.popFrame();
+        if (!this.drawingDeferred) draw(z);
     }
 
     @Override
@@ -241,14 +252,7 @@ public class FontRendererDefault extends FontRenderer {
 
         final List<String> lines = splitCharsIntoLines(chars, maxWidth, this.localStringList);
 
-        GLRenderer.pushFrame();
-        GLRenderer.enableState(State.BLEND);
-        GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
-        GLRenderer.globalSetUniforms(Shaders.FONT);
-        Shaders.FONT.bind();
-        GL41.glUniform1f(Shaders.FONT.getUniform("uZ"), (float) z);
-        this.tessellatorFont.startDrawing();
-
+        if (!this.drawingDeferred) this.tessellatorFont.startDrawing();
         double currY = y;
         switch (alignment) {
             case LEFT: {
@@ -276,9 +280,7 @@ public class FontRendererDefault extends FontRenderer {
                 break;
             }
         }
-        Shaders.FONT.bind();
-        this.tessellatorFont.draw();
-        GLRenderer.popFrame();
+        if (!this.drawingDeferred) draw(z);
 
         if (xPosBuffer != null) {
             xPosBuffer[0] = x + maxWidth;
@@ -299,15 +301,7 @@ public class FontRendererDefault extends FontRenderer {
 
         final List<String> lines = splitCharsIntoLines(chars, maxWidth, this.localStringList);
 
-        GLRenderer.pushFrame();
-        GLRenderer.enableState(State.BLEND);
-        GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
-        GLRenderer.globalSetUniforms(Shaders.FONT);
-        Shaders.FONT.bind();
-        GL41.glUniform1f(Shaders.FONT.getUniform("uZ"), (float) z);
-
-        this.tessellatorFont.startDrawing();
-
+        if (!this.drawingDeferred) this.tessellatorFont.startDrawing();
         int currY = y;
         switch (alignment) {
             case LEFT: {
@@ -335,9 +329,7 @@ public class FontRendererDefault extends FontRenderer {
                 break;
             }
         }
-        Shaders.FONT.bind();
-        this.tessellatorFont.draw();
-        GLRenderer.popFrame();
+        if (!this.drawingDeferred) draw(z);
 
         if (xPosBuffer != null) {
             xPosBuffer[0] = x + maxWidth;
@@ -358,45 +350,26 @@ public class FontRendererDefault extends FontRenderer {
 
         final List<String> lines = splitCharsIntoLines(chars, maxWidth, this.localStringList);
 
+        if (!this.drawingDeferred) this.tessellatorFont.startDrawing();
         double currY = y;
         this.localConfigBuffer[0] = baseConfig;
         switch (alignment) {
             case LEFT: {
-                GLRenderer.pushFrame();
-                GLRenderer.enableState(State.BLEND);
-                GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
-                GLRenderer.globalSetUniforms(Shaders.FONT);
-                Shaders.FONT.bind();
-                GL41.glUniform1f(Shaders.FONT.getUniform("uZ"), (float) z);
-                this.tessellatorFont.startDrawing();
                 for (int i = 0; i < lines.size(); i++) {
                     final String line = lines.get(i);
                     renderStringInternal(font, line, x, currY, z, shadow, baseConfig, null, null, this.localConfigBuffer);
                     currY += font.fontHeight() + 1;
                     if ((currY - y) > maxHeight) break;
                 }
-                Shaders.FONT.bind();
-                this.tessellatorFont.draw();
-                GLRenderer.popFrame();
                 break;
             }
             case RIGHT: {
-                GLRenderer.pushFrame();
-                GLRenderer.enableState(State.BLEND);
-                GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
-                GLRenderer.globalSetUniforms(Shaders.FONT);
-                Shaders.FONT.bind();
-                GL41.glUniform1f(Shaders.FONT.getUniform("uZ"), (float) z);
-                this.tessellatorFont.startDrawing();
                 for (int i = 0; i < lines.size(); i++) {
                     final String line = lines.get(i);
                     renderStringInternal(font, line, x + (maxWidth - stringWidthDouble(line)), currY, z, shadow, baseConfig, null, null, this.localConfigBuffer);
                     currY += font.fontHeight() + 1;
                     if ((currY - y) > maxHeight) break;
                 }
-                Shaders.FONT.bind();
-                this.tessellatorFont.draw();
-                GLRenderer.popFrame();
                 break;
             }
             case CENTERED: {
@@ -409,6 +382,7 @@ public class FontRendererDefault extends FontRenderer {
                 break;
             }
         }
+        if (!this.drawingDeferred) draw(z);
 
         if (xPosBuffer != null) {
             xPosBuffer[0] = x + maxWidth;
diff --git a/game/client/src/main/java/net/minecraft/client/render/renderer/GLRenderer.java b/game/client/src/main/java/net/minecraft/client/render/renderer/GLRenderer.java
index a71958762..ba3709b7e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/renderer/GLRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/renderer/GLRenderer.java
@@ -19,12 +19,9 @@ import org.joml.Vector3fc;
 import org.joml.Vector4dc;
 import org.joml.Vector4f;
 import org.joml.Vector4fc;
-import org.lwjgl.BufferUtils;
 import org.lwjgl.opengl.GL41;
 import org.slf4j.Logger;
 
-import java.nio.FloatBuffer;
-
 import static net.minecraft.client.render.uniform.UniformBlock.N;
 
 public class GLRenderer {
@@ -90,8 +87,8 @@ public class GLRenderer {
     private final Shader[] shaderStack = new Shader[RENDER_FRAMES_STACK_SIZE];
     private @NotNull Shader currentShader = Shaders.INTERFACE;
 
-    private final FogManager.FogState[] fogStateStack = new FogManager.FogState[RENDER_FRAMES_STACK_SIZE];
-    private @NotNull FogManager.FogState currentFogState = new FogManager.FogState().disable();
+    private final @NotNull FogManager.FogState @NotNull [] fogStateStack = new FogManager.FogState[RENDER_FRAMES_STACK_SIZE];
+    private final @NotNull FogManager.FogState currentFogState = new FogManager.FogState().disable();
     private boolean fogStateDirty = true;
 
     private final CompareFunc[] depthFuncStack = new CompareFunc[RENDER_FRAMES_STACK_SIZE];
@@ -135,10 +132,12 @@ public class GLRenderer {
 
 
     private final @NotNull Minecraft mc = Minecraft.getMinecraft();
-    private final FloatBuffer mat4fBuf = BufferUtils.createFloatBuffer(16);
     private final @NotNull TessellatorShader tessellatorShader = new TessellatorShader("GLRender Tessellator", 0x200000);
 
     public GLRenderer() {
+        for (int i = 0; i < this.fogStateStack.length; i++) {
+            this.fogStateStack[i] = new FogManager.FogState().disable();
+        }
     }
 
     public static void init() {
@@ -426,7 +425,7 @@ public class GLRenderer {
         instance.stateConfigStack[instance.stackIndex] = instance.currentStateConfig;
         instance.colorStack[instance.stackIndex] = instance.currentColor;
         instance.shaderStack[instance.stackIndex] = instance.currentShader;
-        instance.fogStateStack[instance.stackIndex] = instance.currentFogState.copy();
+        instance.currentFogState.copy(instance.fogStateStack[instance.stackIndex]);
         instance.depthFuncStack[instance.stackIndex] = instance.currentDepthFunc;
         instance.cullFaceStack[instance.stackIndex] = instance.currentCullFace;
         instance.sFactorStack[instance.stackIndex] = instance.currentSFactor;
@@ -497,7 +496,7 @@ public class GLRenderer {
         if (!instance.currentFogState.equals(instance.fogStateStack[instance.stackIndex])) {
             instance.fogStateDirty = true;
         }
-        instance.currentFogState = instance.fogStateStack[instance.stackIndex];
+        instance.fogStateStack[instance.stackIndex].copy(instance.currentFogState);
 
         if (instance.currentDepthFunc != instance.depthFuncStack[instance.stackIndex]) {
             instance.currentDepthFunc = instance.depthFuncStack[instance.stackIndex];
diff --git a/game/client/src/main/java/net/minecraft/client/render/renderer/Shaders.java b/game/client/src/main/java/net/minecraft/client/render/renderer/Shaders.java
index 9f17936e6..148cba8c8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/renderer/Shaders.java
+++ b/game/client/src/main/java/net/minecraft/client/render/renderer/Shaders.java
@@ -71,8 +71,6 @@ public final class Shaders {
                     entry.getValue().uniformBlockBinding(block.name, block.index);
                 }
                 entry.getValue().bind();
-                GL41.glUniform1i(entry.getValue().getUniform("colortex"), 0);
-                GL41.glUniform1i(entry.getValue().getUniform("lighttex"), 1);
                 entry.getValue().uniformInt("colortex", 0);
                 entry.getValue().uniformInt("lighttex", 1);
                 entry.getValue().uniformInt("emissivetex", 2);
diff --git a/game/client/src/main/java/net/minecraft/client/render/shader/Shader.java b/game/client/src/main/java/net/minecraft/client/render/shader/Shader.java
index 7f63cd00f..a33877451 100644
--- a/game/client/src/main/java/net/minecraft/client/render/shader/Shader.java
+++ b/game/client/src/main/java/net/minecraft/client/render/shader/Shader.java
@@ -116,6 +116,7 @@ public class Shader {
         this.enabled = false;
 
         this.uniformLocations.clear();
+        this.uniformBlockLocations.clear();
 
         OpenGLHelper.checkError("pre delete shader");
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/shader/ShadersRenderer.java b/game/client/src/main/java/net/minecraft/client/render/shader/ShadersRenderer.java
index 1acaff6e8..cb648f933 100644
--- a/game/client/src/main/java/net/minecraft/client/render/shader/ShadersRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/shader/ShadersRenderer.java
@@ -198,8 +198,8 @@ public class ShadersRenderer implements Renderer {
     public void setupFramebuffer() {
         double renderScale = (float) GameSettings.RENDER_SCALE.value.scale;
 
-        int scaledWidth = (int) (renderScale * this.mc.gameWindow.getWidthPixels());
-        int scaledHeight = (int) (renderScale * this.mc.gameWindow.getHeightPixels());
+        int scaledWidth = Math.max((int) (renderScale * this.mc.gameWindow.getWidthPixels()), 1);
+        int scaledHeight = Math.max((int) (renderScale * this.mc.gameWindow.getHeightPixels()), 1);
 
         if (
             this.worldFrameBuffer == null ||
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java
index ccce9eb04..0a6db20a8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java
@@ -13,14 +13,14 @@ import org.joml.primitives.AABBd;
 import net.minecraft.client.render.camera.ICamera;
 import net.minecraft.client.render.culling.CameraFrustum;
 import net.minecraft.core.entity.Entity;
-import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 
 public abstract class ChunkRenderer {
     public static final int MAX_RENDER_PASSES = 2;
     public static int updates = 0;
 
-    public final boolean @NotNull [] empty = new boolean[MAX_RENDER_PASSES];
+//    public final boolean @NotNull [] empty = new boolean[MAX_RENDER_PASSES];
+    public byte emptyBitSet = 0;
 
     public boolean visible = false;
     public int id = -1;
@@ -91,8 +91,10 @@ public abstract class ChunkRenderer {
     }
 
     public void reset() {
+        this.emptyBitSet = 0;
         for (int i = 0; i < MAX_RENDER_PASSES; i++) {
-            this.empty[i] = true;
+//            this.empty[i] = true;
+            this.emptyBitSet |= (byte) (1 << i);
         }
 
         this.visible = false;
@@ -108,11 +110,12 @@ public abstract class ChunkRenderer {
         this.visible = frustum.isVisible(this.bb, partialTick);
     }
 
-    public boolean isEmpty() {
+    public final boolean isEmpty() {
         if (!this.compiled) {
             return false;
         } else {
-            return this.empty[0] && this.empty[1];
+            return this.emptyBitSet == 0b11;
+//            return this.empty[0] && this.empty[1];
         }
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRendererMultiDraw.java b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRendererMultiDraw.java
index a49744192..b9f29d5ec 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRendererMultiDraw.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRendererMultiDraw.java
@@ -124,7 +124,8 @@ public class ChunkRendererMultiDraw extends ChunkRenderer {
             }
 
             if (hasRenderedBlock) {
-                this.empty[renderPass] = false;
+//                this.empty[renderPass] = false;
+                this.emptyBitSet &= (byte) ~(1 << renderPass);
             }
             if (!needsMoreRenderPasses) {
                 break;
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/RegionBuffer.java b/game/client/src/main/java/net/minecraft/client/render/terrain/RegionBuffer.java
index a36419034..8d0da9eeb 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/RegionBuffer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/RegionBuffer.java
@@ -1,18 +1,14 @@
 package net.minecraft.client.render.terrain;
 
-import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-import net.minecraft.client.render.tessellator.TessellatorTerrainImpl;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.UnmodifiableView;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 public class RegionBuffer<V extends VertexConfig<V>> {
     private final @NotNull Int2ObjectMap<@NotNull RenderRegion<V>> regionMap = new Int2ObjectOpenHashMap<>();
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/TerrainRendererMultiDraw.java b/game/client/src/main/java/net/minecraft/client/render/terrain/TerrainRendererMultiDraw.java
index 1fa6d23c5..0d09677e7 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/TerrainRendererMultiDraw.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/TerrainRendererMultiDraw.java
@@ -20,9 +20,9 @@ import java.util.Objects;
 
 public class TerrainRendererMultiDraw extends TerrainRenderer {
 
-    public static final int VERTEX_BUFFER_INITIAL_CAPACITY = 67108864;
+    public static final int VERTEX_BUFFER_INITIAL_CAPACITY = 128 * 1024 * 1024;
 
-    public static final int RENDER_LIST_INITIAL_CAPACITY = 4096;
+    public static final int RENDER_LIST_INITIAL_CAPACITY = 8192;
 
     /**
      * Exponential Region Size
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/VertexBuffer.java b/game/client/src/main/java/net/minecraft/client/render/terrain/VertexBuffer.java
index de715ee04..f52c164ab 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/VertexBuffer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/VertexBuffer.java
@@ -4,7 +4,6 @@ import static org.lwjgl.opengl.GL41.*;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 
 import com.mojang.logging.CategorizedLogger;
 import com.mojang.logging.LogUtils;
@@ -37,7 +36,7 @@ public class VertexBuffer {
         this.vbo = glGenBuffers();
         this.vao = GL41.glGenVertexArrays();
         glBindBuffer(GL_ARRAY_BUFFER, this.vbo);
-        glBufferData(GL_ARRAY_BUFFER, this.capacity, GL_STATIC_DRAW);
+        glBufferData(GL_ARRAY_BUFFER, this.capacity, GL_DYNAMIC_DRAW);
         glBindBuffer(GL_ARRAY_BUFFER, 0);
     }
 
@@ -127,20 +126,20 @@ public class VertexBuffer {
     }
 
     private void expandVBO() {
-        final long prevCapacity = this.capacity;
-        final long newCapacity = this.capacity * 2L;
+//        final long prevCapacity = this.capacity;
+        final long newCapacity = (this.capacity * 3L) >>> 1L;
         if (newCapacity < this.capacity) {
             // future proof
             throw new RuntimeException();
         }
 
-        LOGGER.warn("Expand VBO Buffer: " + newCapacity);
+        LOGGER.warn("Expand VBO Buffer: {}", newCapacity);
 
         OpenGLHelper.checkError("pre expand buffer");
 
         final int newBuffer = glGenBuffers();
         glBindBuffer(GL_ARRAY_BUFFER, newBuffer);
-        glBufferData(GL_ARRAY_BUFFER, newCapacity, GL_STATIC_DRAW);
+        glBufferData(GL_ARRAY_BUFFER, newCapacity, GL_DYNAMIC_DRAW);
 
         OpenGLHelper.checkError("create expand buffer");
 
@@ -154,6 +153,8 @@ public class VertexBuffer {
 
         OpenGLHelper.checkError("copy buffer");
 
+        GL41.glDeleteBuffers(this.vbo); // Delete old buffer
+
         this.capacity = newCapacity;
         this.vbo = newBuffer;
     }
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 837ebd3aa..52f300e11 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
@@ -4,7 +4,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
 import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.option.enums.TextOutlineQuality;
 import net.minecraft.client.render.camera.ICamera;
-import net.minecraft.client.render.font.Font;
 import net.minecraft.client.render.font.FontRendererDefault;
 import net.minecraft.client.render.font.SF;
 import net.minecraft.client.render.renderer.BlendFactor;
@@ -251,13 +250,12 @@ public class TileEntityRendererSign extends TileEntityRenderer<TileEntitySign> {
                 entry.lastUse = System.currentTimeMillis();
                 buffer = entry.buffer;
             } else {
-                Font font = sr.getFont();
-                sr.getTessellator().startDrawing();
-                sr.renderStringRaw(font, line1, -sr.stringWidth(line1) / 2, 0, 0, false, config);
-                sr.renderStringRaw(font, line2, -sr.stringWidth(line2) / 2, 10, 0, false, config);
-                sr.renderStringRaw(font, line3, -sr.stringWidth(line3) / 2, 20, 0, false, config);
-                sr.renderStringRaw(font, line4, -sr.stringWidth(line4) / 2, 30, 0, false, config);
-                buffer = sr.getTessellator().record(GL41.glGenVertexArrays(), GL41.glGenBuffers());
+                sr.startDrawingDeferred();
+                sr.render(line1, -sr.stringWidth(line1) / 2, 0).setConfig(config).call();
+                sr.render(line2, -sr.stringWidth(line2) / 2, 10).setConfig(config).call();
+                sr.render(line3, -sr.stringWidth(line3) / 2, 20).setConfig(config).call();
+                sr.render(line4, -sr.stringWidth(line4) / 2, 30).setConfig(config).call();
+                buffer = sr.record(GL41.glGenVertexArrays(), GL41.glGenBuffers());
                 MeshEntry entry = new MeshEntry(line1, line2, line3, line4, config);
                 entry.buffer = buffer;
                 entry.lastUse = System.currentTimeMillis();
diff --git a/game/client/src/main/java/net/minecraft/client/util/debug/DebugRender.java b/game/client/src/main/java/net/minecraft/client/util/debug/DebugRender.java
index eeaa04eca..63634b71b 100644
--- a/game/client/src/main/java/net/minecraft/client/util/debug/DebugRender.java
+++ b/game/client/src/main/java/net/minecraft/client/util/debug/DebugRender.java
@@ -95,6 +95,7 @@ public class DebugRender {
         int x = w - frametimes.length;
         int y = h;
 
+        t.startDrawingQuads();
         if (selectedProfiler != Debug.baseProfiler) {
             if (w > frametimes.length + baseframetimes.length) {
                 drawFrameTimes(t, x, y, baseframetimes);
@@ -103,6 +104,7 @@ public class DebugRender {
         } else {
             drawFrameTimes(t, 0, y, baseframetimes);
         }
+        t.draw();
 
         GLRenderer.disableState(State.BLEND);
         GLRenderer.setShader(Shaders.INTERFACE);
@@ -117,6 +119,7 @@ public class DebugRender {
         y1 = 0;
         GLRenderer.modelM4f().scale(2.0f, 2.0f, 2.0f);
 
+        sr.startDrawingDeferred();
         int fps = Debug.getFps();
         if (fps >= 0) {
             sr.render("fps: " + fps, x1, y1 - 2 * lineHeight).call();
@@ -132,6 +135,7 @@ public class DebugRender {
             }
             sr.render(i + ": " + profiler.name, x1, y1 + (i + 1) * lineHeight).setColor(color).call();
         }
+        sr.draw(0);
 //		glEnable(GL_ALPHA_TEST);
         GLRenderer.popFrame();
     }
@@ -157,7 +161,6 @@ public class DebugRender {
         int h1 = 16666666 / scale;
         int h2 = 33333333 / scale;
 
-        tessellator.startDrawingQuads();
         tessellator.setColor4i(0, 0, 0, 127);
         drawRectangle(tessellator, x, y - h2, frametimes.length, h2);
         drawRectangle(tessellator, x, y - h1, frametimes.length, h1);
@@ -192,7 +195,6 @@ public class DebugRender {
             drawRectangle(tessellator, x, y - frameLagHeight, frametimes.length, 1);
         }
 
-        tessellator.draw();
     }
 
     private static void drawRectangle(TessellatorGeneral tessellator, int x, int y, int w, int h) {
diff --git a/game/client/src/main/resources/assets/minecraft/textures/art/borders/border_rubyglass.png b/game/client/src/main/resources/assets/minecraft/textures/art/borders/border_rubyglass.png
new file mode 100644
index 000000000..159f63f27
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/art/borders/border_rubyglass.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/entity/arrows.png b/game/client/src/main/resources/assets/minecraft/textures/entity/arrows.png
index 1a17d78d6..f500125cf 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/entity/arrows.png and b/game/client/src/main/resources/assets/minecraft/textures/entity/arrows.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/full/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/full/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/full/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/full/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/full/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/full/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/full/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/full/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/flipped/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/flipped/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/flipped/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/flipped/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/flipped/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/flipped/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/flipped/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/boots/half/flipped/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/full/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/full/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/full/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/full/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/full/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/full/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/full/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/full/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/flipped/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/flipped/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/flipped/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/flipped/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/flipped/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/flipped/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/flipped/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/chestplate/half/flipped/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/full/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/full/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/full/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/full/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/full/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/full/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/full/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/full/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/flipped/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/flipped/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/flipped/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/flipped/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/flipped/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/flipped/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/flipped/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/helmet/half/flipped/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/full/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/full/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/full/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/full/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/full/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/full/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/full/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/full/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/cloth.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/flipped/chainmail.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/flipped/chain.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/flipped/chainmail.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/flipped/chain.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/flipped/leather.png b/game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/flipped/cloth.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/flipped/leather.png
rename to game/client/src/main/resources/assets/minecraft/textures/gui/sprites/hud/armor/leggings/half/flipped/cloth.png
diff --git a/game/client/src/main/resources/credits.txt b/game/client/src/main/resources/credits.txt
index 239dddd9c..2c4c38d9e 100644
--- a/game/client/src/main/resources/credits.txt
+++ b/game/client/src/main/resources/credits.txt
@@ -64,6 +64,7 @@ kheprep
 --Rope texture
 --Pumpkin pie textures
 --Pumpkin crop bush texture
+--Assistance with bug fixes
 Luke (@loquatdev)
 --Assistance with extended controller support
 LukeisStuff
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java b/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java
index d161131d3..241264472 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java
@@ -253,6 +253,11 @@ interface BlockInterface {
         this.onActivatorInteracted(world, new TilePos(x, y, z), activator, direction);
     }
 
+
+    /**
+     * This is only called when the player would make a step noise, and only when they'd make a step noise which makes it
+     * quite hard to actually use for things
+     */
     void onEntityWalkedOn(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Entity walker);
 
     @Deprecated
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java
index 9f0adf63a..4289fa091 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBed.java
@@ -51,11 +51,11 @@ public class BlockLogicBed
             headPos = tilePos;
             footPos = tilePos.sub(f2hDir, new TilePos());
             if (world.getBlockType(footPos) != this.block) return true;
-            data = world.getBlockData(footPos);
         } else {
             footPos = tilePos;
             headPos = tilePos.add(f2hDir, new TilePos());
             if (world.getBlockType(headPos) != this.block) return true;
+            data = world.getBlockData(headPos);
         }
 
         // Explode in invalid dimensions
@@ -79,17 +79,17 @@ public class BlockLogicBed
             for (final @NotNull Player p : world.players) {
                 if (!p.isPlayerSleeping()) continue;
                 final var otherBedPos = Objects.requireNonNull(p.bedTilePos);
-                if (otherBedPos.equals(footPos)) {
-                    player.sendMessageTranslated("messages.bed.occupied");
+                if (otherBedPos.equals(headPos)) {
+                    player.sendStatusMessageTranslated("messages.bed.occupied");
                     return true;
                 }
             }
-            world.setBlockData(footPos, IS_OCCUPIED.set(data, 0));
+            world.setBlockData(headPos, IS_OCCUPIED.set(data, 0));
         }
         
         // Sleep
-        if (player.sleepInBedAt(footPos.x(), footPos.y(), footPos.z()) == EnumSleepStatus.OK) {
-            world.setBlockData(footPos, IS_OCCUPIED.set(data, 1));
+        if (player.sleepInBedAt(headPos.x(), headPos.y(), headPos.z()) == EnumSleepStatus.OK) {
+            world.setBlockData(headPos, IS_OCCUPIED.set(data, 1));
         }
 
         return true;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicConduit.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicConduit.java
index 66ac6c306..cb86b616d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicConduit.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicConduit.java
@@ -334,17 +334,19 @@ public class BlockLogicConduit extends BlockLogic {
     }
 
     private static boolean isEmitting(@NotNull WorldSource world, @NotNull TilePosc tilePos, @NotNull Side side) {
-        int data = world.getBlockData(tilePos);
-        int currentPower = (data >> POWER_SHIFT) & POWER_MASK;
+        final int data = world.getBlockData(tilePos);
+        if ((data & STATE_MASK) == 0) return false;
 
+        final int currentPower = (data >>> POWER_SHIFT) & POWER_MASK;
         if (currentPower == 0) return false;
 
-        TilePos receiverPos = new TilePos(tilePos).add(side.opposite());
-        if (world.getBlockType(receiverPos) == Blocks.WIRE_REDSTONE) {
+        final Side sideAgainst = side.opposite();
+
+        final Block<?> receiver = world.getBlockType(new TilePos(tilePos).add(sideAgainst));
+        if (receiver == Blocks.WIRE_REDSTONE || receiver == Blocks.CONDUIT) {
             return false;
         }
-
-        return isSideOpen(data, side.opposite());
+        return isSideOpen(data, sideAgainst);
     }
 
     private int getNextState(int currentState, @NotNull Side sideQueried) {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicEmber.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicEmber.java
index 31c37986c..e32631874 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicEmber.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicEmber.java
@@ -5,11 +5,17 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.animal.MobWolf;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.util.helper.DamageType;
+import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.HitResult;
 import net.minecraft.core.world.World;
+import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.pos.TilePos;
 import net.minecraft.core.world.pos.TilePosc;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.joml.Vector3d;
+import org.joml.primitives.AABBd;
+import org.joml.primitives.AABBdc;
 
 import java.util.Random;
 
@@ -36,7 +42,15 @@ public class BlockLogicEmber extends BlockLogic {
 		if (entity != null) {
 			entity.hurt(null, 8, DamageType.BLAST);
 			entity.remainingFireTicks = 100;
-			entity.fling(1.0f, 1.0f, 1.0f, 0.0f);
+			double xd = entity.xd;
+			double zd = entity.zd;
+			double len = Math.sqrt(xd * xd + zd * zd);
+			if (len == 0) {
+				entity.fling(0, 0.65, 0, 0.25F);
+			} else {
+				double f = org.joml.Math.clamp(0.1, 1, len);
+				entity.fling((xd/len) * f, 0.65, (zd/len) * f, 0.25F);
+			}
 		}
 
 		world.setBlockType(tilePos, Blocks.AIR);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java
index 9318f640f..3acad5f13 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java
@@ -229,4 +229,12 @@ public class BlockLogicFluidFlowing extends BlockLogicFluid {
             world.scheduleBlockUpdate(tilePos, this.block, tickDelay(world, tilePos));
         }
     }
+
+    @Override
+    public void onNeighborChanged(@NotNull World world, @NotNull TilePosc tilePos, final @NotNull Block<?> block) {
+        super.onNeighborChanged(world, tilePos, block);
+        if (world.getBlockType(tilePos) == this.block) {
+            world.scheduleBlockUpdate(tilePos, this.block, tickDelay(world, tilePos));
+        }
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerBase.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerBase.java
index 628d9c951..30776c77a 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerBase.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerBase.java
@@ -59,6 +59,10 @@ public abstract class BlockLogicLayerBase extends BlockLogic
 
     @Override
     public @NotNull AABBdc getBoundsFromState(@NotNull WorldSource source, @NotNull TilePosc tilePos) {
+        return this.getBoundsFromStateMut(source, tilePos);
+    }
+
+    protected @NotNull AABBd getBoundsFromStateMut(@NotNull WorldSource source, @NotNull TilePosc tilePos) {
         int data = source.getBlockData(tilePos) & MASK_HEIGHT;
         float f = (float)(2 * (1 + data)) / 16F;
         return new AABBd(0.0F, 0.0F, 0.0F, 1.0F, f, 1.0F);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerLeaves.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerLeaves.java
index 8df6d9034..13b1d03e7 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerLeaves.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerLeaves.java
@@ -1,10 +1,12 @@
 package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.TileEntity;
+import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.block.ItemBlockLayerLeaves;
 import net.minecraft.core.util.helper.Direction;
+import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.world.WorldSource;
@@ -73,6 +75,11 @@ public class BlockLogicLayerLeaves extends BlockLogicLayerSupportable {
         }
     }
 
+    @Override
+    public int getPlacedData(@Nullable Player player, @NotNull ItemStack itemStack, @NotNull World world, @NotNull TilePosc tilePos, @NotNull Side side, double xHit, double yHit) {
+        return MASK_PERMANENT;
+    }
+
     public static boolean isPermanent(int meta) {
         return (meta & MASK_PERMANENT) != 0;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSnow.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSnow.java
index cf5f41b1a..9f3b9809b 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSnow.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLayerSnow.java
@@ -29,8 +29,8 @@ public class BlockLogicLayerSnow extends BlockLogicLayerSupportable {
     }
 
     public void accumulate(@NotNull World world, @NotNull TilePosc tilePos) {
-        int myMetadata = world.getBlockData(tilePos);
-        if (myMetadata == 0x7) return;
+        final int myMetadata = world.getBlockData(tilePos);
+        if (myMetadata >= 6) return;
 
         for (final var dir : Direction.horizontal) {
             TilePos dirPos = tilePos.add(dir, new TilePos());
@@ -44,8 +44,9 @@ public class BlockLogicLayerSnow extends BlockLogicLayerSupportable {
 
     @Override
     public @Nullable AABBdc getCollisionAABB(@NotNull WorldSource source, @NotNull TilePosc tilePos) {
-        final AABBdc aabb = getBounds();
-        return new AABBd(aabb).setMax(aabb.maxX(), Math.max(aabb.maxY() - 2 / 16f, tilePos.y()), aabb.maxZ());
+        final AABBd aabb = this.getBoundsFromStateMut(source, tilePos);
+        aabb.maxY = Math.max(aabb.minY, aabb.maxY - 2 / 16F);
+        return aabb.translate(tilePos.x(), tilePos.y(), tilePos.z());
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java
index 28a8042b0..087ecd16f 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java
@@ -365,14 +365,13 @@ public class BlockLogicPistonBase extends BlockLogic {
 
         final TilePos query1 = new TilePos(), query2 = new TilePos();
         final var headPos = new TilePos(basePos).add(dir);
-        final TilePosc sourcePos = query1.set(basePos).add(dir).add(dir, new TilePos());
-
+        final TilePosc sourcePos = headPos.add(dir, new TilePos());
 
         final int len = LINE_LENGTH.get(lineInfo);
 
-        if (world.getTileEntity(headPos) instanceof TileEntityMovingPistonBlock moving && !moving.isExtending) {
-            moving.finalTick();
-        }
+        // if (world.getTileEntity(headPos) instanceof TileEntityMovingPistonBlock moving && !moving.isExtending) {
+        //     moving.finalTick();
+        // }
         world.setBlockTypeRaw(headPos, Blocks.AIR);
         world.removeTileEntity(headPos);
         final var moving = new TileEntityMovingPistonBlock(
@@ -381,6 +380,11 @@ public class BlockLogicPistonBase extends BlockLogic {
         world.setBlockTypeRaw(basePos, Blocks.AIR);
         world.setBlockTypeDataEntity(basePos, Blocks.PISTON_MOVING, data, moving);
 
+
+        if (world.getTileEntity(sourcePos) instanceof TileEntityMovingPistonBlock zeroTicker && zeroTicker.isExtending) {
+            zeroTicker.finalTick();
+        }
+
         if (len > 0) {
             final var line = new MovingLine(len, world, dir, sourcePos, false);
             line.init(query1);
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java b/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java
index 0dfc65837..158c6cec8 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/TileEntityMovingPistonBlock.java
@@ -18,7 +18,7 @@ import org.joml.primitives.AABBd;
 import org.joml.primitives.AABBdc;
 
 import java.util.*;
-import static net.minecraft.core.block.piston.PistonCommon.*;
+// import static net.minecraft.core.block.piston.PistonCommon.*;
 
 /**
  * TODO: make movingTileEntity tick the moving block
@@ -33,10 +33,8 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
     @Nullable TileEntity movingTileEntity;
 
     @NotNull Direction direction;
-    boolean isExtending;
-    boolean isSourcePiston;
-    int lifetime = 0;
-    long lastTick;
+    boolean isExtending, isSourcePiston;
+    int lifetime, latestTick;
     float progressCur = 0F, progressPrev = 0F;
 
     // these would otherwise be reallocated each tick, might as well store them here
@@ -60,7 +58,7 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
     // awkward
     // TODO provide an actual initiallization event that is guaranteed to be called after
     // TODO   tile entity is valid (i.e. not .validate())
-    private boolean isCollisionInited = false;
+    private boolean isCollisionInit = false;
 
     public @NotNull Block<?> movingBlock() { return this.movingBlock; }
     public int movingBlockData() { return this.movingBlockData; }
@@ -86,15 +84,24 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
         @NotNull Block<?> movingBlock, int movingData, @Nullable TileEntity movingEntity, 
         @NotNull Direction direction
     ) {
-        assert movingBlock != Blocks.PISTON_MOVING;
         this.movingBlock = movingBlock;
         this.movingBlockData = movingData;
         this.movingTileEntity = movingEntity;
         this.direction = direction;
         this.isExtending = type.isExtending;
         this.isSourcePiston = type.isSourcePiston;
+
+        if (this.isNested()) {
+            this.tileEntityInvalid = true;
+            LOGGER.warn("attempting to construct a nested TileEntityMovingPistonBlock. invalidated!");
+            return;
+        }
     }
 
+    protected final boolean isNested() {
+        return this.movingBlock == Blocks.PISTON_MOVING || this.movingTileEntity instanceof TileEntityMovingPistonBlock;
+    } 
+
     @Override
     public void validate() {
         super.validate();
@@ -129,14 +136,17 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
         }
         ctx.collisions.clear();
 
-        this.isCollisionInited = true;
+        this.isCollisionInit = true;
     }
 
 
     @Override
     public void tick() {
-        if (!this.isCollisionInited) this.initCollision();
-        this.lastTick = this.worldObj.getWorldTime();
+        assert !this.isNested();
+
+        if (!this.isCollisionInit) this.initCollision();
+
+        this.latestTick = (int) this.worldObj.getWorldTime(); // using only the lower 32 bit should be enough
         if (this.lifetime ++ >= TICKS_TO_EXTEND) {
             this.finalTick();
         } else {
@@ -171,7 +181,7 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
 
     public boolean isInFinalTick() {
         if (this.lifetime < TICKS_TO_EXTEND) return false;
-        return this.lastTick + 1 >= this.worldObj.getWorldTime();
+        return this.latestTick + 1 >= (int)this.worldObj.getWorldTime();
     }
 
     public float xOffset(float partialTick) {
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java b/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
index 3eed062cb..8404437e9 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
@@ -58,6 +58,7 @@ public final class EntityDispatcher
     public final EntityFactory<ProjectilePebble> FACTORY_PROJECTILE_PEBBLE;
     public final EntityFactory<ProjectileEgg> FACTORY_PROJECTILE_EGG;
     public final EntityFactory<ProjectileArrow> FACTORY_PROJECTILE_ARROW;
+    public final EntityFactory<ProjectileArrowFlaming> FACTORY_PROJECTILE_ARROW_FLAMING;
     public final EntityFactory<ProjectileArrowGolden> FACTORY_PROJECTILE_ARROW_GOLDEN;
     public final EntityFactory<ProjectileArrowPurple> FACTORY_PROJECTILE_ARROW_PURPLE;
     public final EntityFactory<ProjectileSnowball> FACTORY_PROJECTILE_SNOWBALL;
@@ -106,6 +107,7 @@ public final class EntityDispatcher
         FACTORY_PROJECTILE_PEBBLE = addMapping(ProjectilePebble.class, NamespaceID.fromPool("minecraft", "pebble"), ProjectilePebble::new);
         FACTORY_PROJECTILE_EGG = addMapping(ProjectileEgg.class, NamespaceID.fromPool("minecraft", "egg"), ProjectileEgg::new);
         FACTORY_PROJECTILE_ARROW = addMapping(ProjectileArrow.class, NamespaceID.fromPool("minecraft", "arrow"), ProjectileArrow::new);
+        FACTORY_PROJECTILE_ARROW_FLAMING = addMapping(ProjectileArrowFlaming.class, NamespaceID.fromPool("minecraft", "arrow_flaming"), ProjectileArrowFlaming::new);
         FACTORY_PROJECTILE_ARROW_GOLDEN = addMapping(ProjectileArrowGolden.class, NamespaceID.fromPool("minecraft", "arrow_golden"), ProjectileArrowGolden::new);
         FACTORY_PROJECTILE_ARROW_PURPLE = addMapping(ProjectileArrowPurple.class, NamespaceID.fromPool("minecraft", "arrow_purple"), ProjectileArrowPurple::new);
         FACTORY_PROJECTILE_SNOWBALL = addMapping(ProjectileSnowball.class, NamespaceID.fromPool("minecraft", "snowball"), ProjectileSnowball::new);
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java b/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java
index 7913026e0..41efa32bd 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityPainting.java
@@ -350,5 +350,6 @@ public class EntityPainting extends Entity {
         addBorder(Items.DUST_REDSTONE.getDefaultStack(), NamespaceID.fromPool("minecraft", "border_redstone"));
         addBorder(Items.OLIVINE.getDefaultStack(), NamespaceID.fromPool("minecraft", "border_olivine"));
         addBorder(Items.QUARTZ.getDefaultStack(), NamespaceID.fromPool("minecraft", "border_quartz"));
+        addBorder(Items.RUBYGLASS.getDefaultStack(), NamespaceID.fromPool("minecraft", "border_rubyglass"));
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
index e0a0e7dc9..952344690 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
@@ -1296,7 +1296,7 @@ public abstract class Player
             }
             if (this.bedTilePos == null || !this.bedTilePos.equals(new TilePos(x, y, z))) {
                 if (this.playerSpawnPoint == null || !this.playerSpawnPoint.equals(new TilePos(x, y, z))) {
-                    sendMessageTranslated("messages.bed.setSpawn");
+                    sendStatusMessageTranslated("messages.bed.setSpawn");
                     setPlayerSpawnPoint(new TilePos(x, y, z));
                 }
             }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java
index be64c4154..4a0c404fa 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrow.java
@@ -23,6 +23,7 @@ public class ProjectileArrow extends Projectile {
     public static final int TYPE_NORMAL = 0;
     public static final int TYPE_PURPLE = 1;
     public static final int TYPE_GOLDEN = 2;
+    public static final int TYPE_FLAMING = 3;
     protected int mobsHit = 0;
     protected @Nullable TilePos tilePos = null;
     protected @Nullable Block<?> inTile = null;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrowFlaming.java b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrowFlaming.java
index 1cedf70ab..f4220a2ee 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrowFlaming.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/projectile/ProjectileArrowFlaming.java
@@ -18,19 +18,19 @@ import org.jetbrains.annotations.NotNull;
 
 public class ProjectileArrowFlaming extends ProjectileArrow {
 	public ProjectileArrowFlaming(World world) {
-		super(world, 4);
+		super(world, TYPE_FLAMING);
 		this.stack = new ItemStack(Items.AMMO_ARROW_FLAMING);
 		this.entityBrightness = 1.0F;
 	}
 
 	public ProjectileArrowFlaming(World world, double x, double y, double z) {
-		super(world, x, y, z, 4);
+		super(world, x, y, z, TYPE_FLAMING);
 		this.stack = new ItemStack(Items.AMMO_ARROW_FLAMING);
 		this.entityBrightness = 1.0F;
 	}
 
 	public ProjectileArrowFlaming(World world, Mob owner, boolean doesArrowBelongToPlayer) {
-		super(world, owner, doesArrowBelongToPlayer, 4);
+		super(world, owner, doesArrowBelongToPlayer, TYPE_FLAMING);
 		this.stack = new ItemStack(Items.AMMO_ARROW_FLAMING);
 		this.entityBrightness = 1.0F;
 	}
diff --git a/game/core/src/main/java/net/minecraft/core/net/entity/NetEntityHandler.java b/game/core/src/main/java/net/minecraft/core/net/entity/NetEntityHandler.java
index 99a71308e..03dcc762e 100644
--- a/game/core/src/main/java/net/minecraft/core/net/entity/NetEntityHandler.java
+++ b/game/core/src/main/java/net/minecraft/core/net/entity/NetEntityHandler.java
@@ -134,7 +134,5 @@ public class NetEntityHandler {
         registerNetworkEntry(new NetEntryPrimedTNT(), 21);
 
         registerNetworkEntry(new NetEntryBobber(), 30);
-
-        registerNetworkEntry(new NetEntryArrowFlaming(), 32);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryArrow.java b/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryArrow.java
index 7cc81e254..acb9b8203 100644
--- a/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryArrow.java
+++ b/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryArrow.java
@@ -4,6 +4,7 @@ import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.entity.projectile.ProjectileArrow;
+import net.minecraft.core.entity.projectile.ProjectileArrowFlaming;
 import net.minecraft.core.entity.projectile.ProjectileArrowGolden;
 import net.minecraft.core.entity.projectile.ProjectileArrowPurple;
 import net.minecraft.core.net.entity.EntityTracker;
@@ -43,20 +44,20 @@ public class NetEntryArrow implements IVehicleEntry<ProjectileArrow>, ITrackedEn
 
     @Override
     public Entity getEntity(World world, double x, double y, double z, int metadata, boolean hasVelocity, double xd, double yd, double zd, Entity owner, @Nullable CompoundTag tag) {
-        if (metadata == 2) {
-            return new ProjectileArrowGolden(world, x, y, z);
-        } else if (metadata == 1) {
-            return new ProjectileArrowPurple(world, x, y, z);
-        } else {
-            return new ProjectileArrow(world, x, y, z, metadata);
-        }
+        return switch (metadata) {
+            case ProjectileArrow.TYPE_NORMAL -> new ProjectileArrow(world, x, y, z, metadata);
+            case ProjectileArrow.TYPE_PURPLE -> new ProjectileArrowPurple(world, x, y, z);
+            case ProjectileArrow.TYPE_GOLDEN -> new ProjectileArrowGolden(world, x, y, z);
+            case ProjectileArrow.TYPE_FLAMING -> new ProjectileArrowFlaming(world, x, y, z);
+            default -> new ProjectileArrow(world, x, y, z, metadata);
+        };
     }
 
     @Override
     public PacketAddEntity getSpawnPacket(EntityTrackerEntry tracker, ProjectileArrow trackedObject) {
-        Mob entityliving = trackedObject.owner;
+        Mob owner = trackedObject.owner;
         return new PacketAddEntity(trackedObject,
-            trackedObject.getArrowType(), entityliving == null ? -1 : entityliving.id,
+            trackedObject.getArrowType(), owner == null ? -1 : owner.id,
             trackedObject.xd, trackedObject.yd, trackedObject.zd);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryArrowFlaming.java b/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryArrowFlaming.java
deleted file mode 100644
index 03f87625c..000000000
--- a/game/core/src/main/java/net/minecraft/core/net/entity/entries/NetEntryArrowFlaming.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package net.minecraft.core.net.entity.entries;
-
-import com.mojang.nbt.tags.CompoundTag;
-import net.minecraft.core.entity.Entity;
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.projectile.ProjectileArrowFlaming;
-import net.minecraft.core.net.entity.EntityTracker;
-import net.minecraft.core.net.entity.EntityTrackerEntry;
-import net.minecraft.core.net.entity.ITrackedEntry;
-import net.minecraft.core.net.entity.IVehicleEntry;
-import net.minecraft.core.net.packet.PacketAddEntity;
-import net.minecraft.core.world.World;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class NetEntryArrowFlaming implements IVehicleEntry<ProjectileArrowFlaming>, ITrackedEntry<ProjectileArrowFlaming> {
-
-	public NetEntryArrowFlaming() {
-	}
-
-	@Override
-	public @NotNull Class<ProjectileArrowFlaming> getAppliedClass() {
-		return ProjectileArrowFlaming.class;
-	}
-
-	@Override
-	public int getTrackingDistance() {
-		return 64;
-	}
-
-	@Override
-	public int getMovementPacketDelay() {
-		return 20;
-	}
-
-	@Override
-	public boolean sendMotionUpdates() {
-		return false;
-	}
-
-	@Override
-	public void onEntityTracked(EntityTracker tracker, EntityTrackerEntry trackerEntry, ProjectileArrowFlaming trackedObject) {
-	}
-
-	@Override
-	public Entity getEntity(World world, double x, double y, double z, int metadata, boolean hasVelocity, double xd, double yd, double zd, Entity owner, @Nullable CompoundTag tag) {
-		return new ProjectileArrowFlaming(world, x, y, z);
-	}
-
-	@Override
-	public PacketAddEntity getSpawnPacket(EntityTrackerEntry tracker, ProjectileArrowFlaming trackedObject) {
-		Mob entityliving = trackedObject.owner;
-		return new PacketAddEntity(trackedObject, 0, entityliving == null ? -1 : entityliving.id, trackedObject.xd, trackedObject.yd, trackedObject.zd);
-	}
-}
diff --git a/game/core/src/main/java/net/minecraft/core/util/helper/MathHelper.java b/game/core/src/main/java/net/minecraft/core/util/helper/MathHelper.java
index 7abca18e0..d5770297c 100644
--- a/game/core/src/main/java/net/minecraft/core/util/helper/MathHelper.java
+++ b/game/core/src/main/java/net/minecraft/core/util/helper/MathHelper.java
@@ -573,4 +573,12 @@ public class MathHelper {
 
         return value;
     }
+
+    public static float floorMod(float x, float y) {
+        return (float) (x - Math.floor(x / y) * y);
+    }
+
+    public static double floorMod(double x, double y) {
+        return (x - Math.floor(x / y) * y);
+    }
 }
diff --git a/game/core/src/main/resources/assets/minecraft/lang/en_US/options.lang b/game/core/src/main/resources/assets/minecraft/lang/en_US/options.lang
index bf8544bbf..11bdbdeb3 100644
--- a/game/core/src/main/resources/assets/minecraft/lang/en_US/options.lang
+++ b/game/core/src/main/resources/assets/minecraft/lang/en_US/options.lang
@@ -439,4 +439,5 @@ key.debug.reloadchunks=Reload chunks
 key.debug.smoothlighting=Toggle smooth lighting
 key.debug.releasecursor=Release Cursor
 key.debug.shortcuts=Show keyboard shortcuts
-key.debug.loadChunksQuickly=Load Chunks Quickly
\ No newline at end of file
+key.debug.loadChunksQuickly=Load Chunks Quickly
+key.debug.toggleFrameLimit=Toggle Frame Limit
\ No newline at end of file
diff --git a/game/server/src/main/java/net/minecraft/server/world/WorldServer.java b/game/server/src/main/java/net/minecraft/server/world/WorldServer.java
index 8be6bfd6a..04cc95bc3 100644
--- a/game/server/src/main/java/net/minecraft/server/world/WorldServer.java
+++ b/game/server/src/main/java/net/minecraft/server/world/WorldServer.java
@@ -168,12 +168,11 @@ public class WorldServer extends World {
         final int required = getPlayersRequiredToSkipNight();
         int playersSleeping = 0;
         for (final var p : players) {
-            if (!p.isPlayerSleeping()) break;
-            if (playersSleeping >= required) {
+            if (!p.isPlayerSleeping()) continue;
+            if (++playersSleeping >= required) {
                 this.enoughPlayersSleeping = true;
                 break;
             }
-            playersSleeping++;
         }
 
         if (player == null) return;
