diff --git a/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/sounds.json b/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/sounds.json
index df97bd7cf..606273548 100644
--- a/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/sounds.json
+++ b/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/sounds.json
@@ -8,15 +8,15 @@
       "tile/bubble_4.ogg"
     ]
   },
-  "step.crystal": {
-    "subtitle": "subtitles.step.crystal",
+  "tile.crystal": {
+    "subtitle": "subtitles.tile.crystal",
     "sounds": [
-      "step/crystal_1.ogg",
-      "step/crystal_2.ogg",
-      "step/crystal_3.ogg",
-      "step/crystal_4.ogg",
-      "step/crystal_5.ogg",
-      "step/crystal_6.ogg"
+      "tile/crystal_1.ogg",
+      "tile/crystal_2.ogg",
+      "tile/crystal_3.ogg",
+      "tile/crystal_4.ogg",
+      "tile/crystal_5.ogg",
+      "tile/crystal_6.ogg"
     ]
   },
   "tile.deep.boom": {
@@ -44,10 +44,10 @@
       "tile/deepcrumble.ogg"
     ]
   },
-  "random.scrape": {
-    "subtitle": "subtitles.random.scrape",
+  "tile.scrape": {
+    "subtitle": "subtitles.tile.scrape",
     "sounds": [
-      "random/scrape.ogg"
+      "tile/scrape.ogg"
     ]
   },
   "music.bta.overworld": {
diff --git a/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_1.ogg b/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_1.ogg
similarity index 100%
rename from game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_1.ogg
rename to game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_1.ogg
diff --git a/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_2.ogg b/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_2.ogg
similarity index 100%
rename from game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_2.ogg
rename to game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_2.ogg
diff --git a/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_3.ogg b/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_3.ogg
similarity index 100%
rename from game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_3.ogg
rename to game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_3.ogg
diff --git a/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_4.ogg b/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_4.ogg
similarity index 100%
rename from game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_4.ogg
rename to game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_4.ogg
diff --git a/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_5.ogg b/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_5.ogg
similarity index 100%
rename from game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_5.ogg
rename to game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_5.ogg
diff --git a/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_6.ogg b/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_6.ogg
similarity index 100%
rename from game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/crystal_6.ogg
rename to game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/crystal_6.ogg
diff --git a/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/scrape.ogg b/game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/scrape.ogg
similarity index 100%
rename from game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/scrape.ogg
rename to game/client/devPacks/inTestingSoundsPack/assets/minecraft/sounds/tile/scrape.ogg
diff --git a/game/client/setup_bg.sh b/game/client/setup_bg.sh
old mode 100644
new mode 100755
index 25860dba5..539400af7
--- a/game/client/setup_bg.sh
+++ b/game/client/setup_bg.sh
@@ -3,7 +3,7 @@
 ROOT_DIR=./src/main/resources/bg
 
 for filename in "${ROOT_DIR}"/*.png; do
-    if ! magick identify "${filename}" | grep "512x256" > /dev/null; then
+    if ! magick identify "${filename}" | grep "1024x512" > /dev/null; then
         echo "${filename}"
         magick "${filename}" \
             -define filter:blur=3 \
@@ -11,9 +11,9 @@ for filename in "${ROOT_DIR}"/*.png; do
             -define png:format=png24 \
             -define png:compression-strategy=3 \
             -filter Lagrange \
-            -resize 512 \
+            -resize 1024 \
             -gravity center \
-            -crop 512x256+0+0 \
+            -crop 1024x512+0+0 \
             +repage \
             "${filename}"
     fi
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 eeffad659..d19a667a5 100644
--- a/game/client/src/main/java/net/minecraft/client/Minecraft.java
+++ b/game/client/src/main/java/net/minecraft/client/Minecraft.java
@@ -146,8 +146,6 @@ import net.minecraft.core.world.save.LevelStorage;
 import net.minecraft.core.world.save.SaveConverters;
 import net.minecraft.core.world.save.SaveFormatBase;
 import net.minecraft.core.world.save.SaveFormats;
-import net.minecraft.core.world.save.mcregion.SaveFormat19134;
-import net.minecraft.core.world.save.mcregion.SaveFormat19135;
 import net.minecraft.core.world.settings.WorldConfiguration;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -480,7 +478,10 @@ public class Minecraft
 
         this.resolution.setScale(GameSettings.GUI_SCALE.value);
 
-        SaveFormatBase handlerBase = new SaveFormat19135(new File(this.mcDataDir, "saves"));
+        ISaveFormat activeFormat = SaveFormats.createSaveFormat(CURRENT_SAVE_VERSION, new File(this.mcDataDir, "saves"));
+        if (!(activeFormat instanceof SaveFormatBase handlerBase)) {
+            throw new IllegalStateException("No save format registered for current save version " + CURRENT_SAVE_VERSION);
+        }
         handlerBase.factory = LevelStorageClientSP::new;
         this.saveFormat = handlerBase;
         I18n.initialize(GameSettings.LANGUAGE.value);
@@ -2180,42 +2181,67 @@ public class Minecraft
     }
 
     private void convertSaveVersion(int fromVersion, String worldDirName) {
-        ISaveFormat fromWorldFormat = SaveFormats.createSaveFormat(fromVersion, new File(this.mcDataDir, "saves"));
+        int currentVersion = fromVersion;
+        while (currentVersion < CURRENT_SAVE_VERSION) {
+            ISaveFormat fromWorldFormat = SaveFormats.createSaveFormat(currentVersion, new File(this.mcDataDir, "saves"));
+            if (fromWorldFormat == null) {
+                break;
+            }
 
-        if (fromWorldFormat != null) {
-            // Get highest converter
             ISaveConverter converterToUse = null;
             for (ISaveConverter converter : SaveConverters.saveConverters) {
-                if (converter.fromVersion() == fromVersion) {
+                if (converter.fromVersion() == currentVersion) {
                     if (converterToUse == null || converter.toVersion() > converterToUse.toVersion()) {
                         converterToUse = converter;
                     }
                 }
             }
+            if (converterToUse == null) {
+                break;
+            }
+            if (converterToUse.toVersion() <= currentVersion) {
+                LOGGER.warn("World conversion halted for '{}' due to non-advancing converter {} -> {}.", worldDirName, converterToUse.fromVersion(), converterToUse.toVersion());
+                break;
+            }
 
-            if (converterToUse != null) {
-                ISaveFormat toWorldFormat = SaveFormats.createSaveFormat(converterToUse.toVersion(), new File(this.mcDataDir, "saves"));
-
-                if (toWorldFormat != null) {
-                    this.loadingScreen.updateLoadingBackground(null);
-                    this.loadingScreen.progressStartNoAbort("Converting world from " + fromWorldFormat.getFormatName() + " to " + toWorldFormat.getFormatName() + ".");
-                    this.loadingScreen.progressStage("This may take a while :)");
+            ISaveFormat toWorldFormat = SaveFormats.createSaveFormat(converterToUse.toVersion(), new File(this.mcDataDir, "saves"));
+            if (toWorldFormat == null) {
+                break;
+            }
 
-                    CompoundTag levelDataTag = toWorldFormat.getLevelDataRaw(worldDirName);
+            this.loadingScreen.updateLoadingBackground(null);
+            this.loadingScreen.progressStartNoAbort("Converting world from " + fromWorldFormat.getFormatName() + " to " + toWorldFormat.getFormatName() + ".");
+            String formatMessage = toWorldFormat.getFormatMessage();
+            this.loadingScreen.progressStage((formatMessage == null || formatMessage.isEmpty()) ? "This may take a while :)" : formatMessage);
 
-                    converterToUse.convertSave(levelDataTag, new File(this.mcDataDir, "saves"), worldDirName, this.loadingScreen);
+            CompoundTag levelDataTag = toWorldFormat.getLevelDataRaw(worldDirName);
+            converterToUse.convertSave(levelDataTag, new File(this.mcDataDir, "saves"), worldDirName, this.loadingScreen);
+            this.loadingScreen.progressStop();
 
-                    this.loadingScreen.progressStop();
+            levelDataTag.putInt("version", toWorldFormat.getSaveVersion());
+            LevelStorage saveHandler = toWorldFormat.getLevelStorage(worldDirName, false);
+            saveHandler.saveLevelDataRaw(levelDataTag);
 
-                    levelDataTag.putInt("version", toWorldFormat.getSaveVersion());
+            CompoundTag reloadedLevelData = toWorldFormat.getLevelDataRaw(worldDirName);
+            int reloadedVersion = reloadedLevelData != null ? reloadedLevelData.getInteger("version") : -1;
+            if (reloadedVersion < toWorldFormat.getSaveVersion()) {
+                LOGGER.warn("World conversion write verification failed for '{}' (expected >= {}, got {}).", worldDirName, toWorldFormat.getSaveVersion(), reloadedVersion);
+                break;
+            }
 
-                    LevelStorage saveHandler = toWorldFormat.getLevelStorage(worldDirName, false);
-                    saveHandler.saveLevelDataRaw(levelDataTag);
+            currentVersion = reloadedVersion;
+        }
 
-                    startWorld(worldDirName);
-                }
+        ISaveFormat currentFormat = SaveFormats.createSaveFormat(CURRENT_SAVE_VERSION, new File(this.mcDataDir, "saves"));
+        if (currentFormat != null) {
+            CompoundTag finalLevelData = currentFormat.getLevelDataRaw(worldDirName);
+            if (finalLevelData != null && finalLevelData.getInteger("version") < CURRENT_SAVE_VERSION) {
+                finalLevelData.putInt("version", CURRENT_SAVE_VERSION);
+                currentFormat.getLevelStorage(worldDirName, false).saveLevelDataRaw(finalLevelData);
             }
         }
+
+        startWorld(worldDirName);
     }
 
     private void prepareLevel(String loadingTitle) {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenHudEditor.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenHudEditor.java
index 39e559808..4a63e1bb0 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenHudEditor.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenHudEditor.java
@@ -444,9 +444,12 @@ public class ScreenHudEditor extends Screen {
         drawHudComponents(mx, my);
 
         if (this.heldComponent != null && this.isDragging) {
+            int padding = (int) GameSettings.SCREEN_PADDING.value.floatValue();
+            int usableWidth = Math.max(1, this.width - padding * 2);
+            int usableHeight = Math.max(1, this.height - padding * 2);
             for (ComponentAnchor anchor : ComponentAnchor.values()) {
                 if (anchor == ComponentAnchor.CENTER) continue;
-                drawAnchor(0, 0, (int) (this.width * anchor.xPosition), (int) (this.height * anchor.yPosition), anchor);
+                drawAnchor(padding, padding, (int) (usableWidth * anchor.xPosition), (int) (usableHeight * anchor.yPosition), anchor);
             }
         }
 
@@ -579,13 +582,20 @@ public class ScreenHudEditor extends Screen {
         int ySize = this.heldComponent.getDisplayedYSize();
         int xOffset = this.heldComponent.getDisplayedAnchorX(this.heldAnchor);
         int yOffset = this.heldComponent.getDisplayedAnchorY(this.heldAnchor);
-        int newX = MathHelper.clamp(mouseX, xOffset, this.width - (xSize - xOffset));
-        int newY = MathHelper.clamp(mouseY, yOffset, this.height - (ySize - yOffset));
+        int padding = (int) GameSettings.SCREEN_PADDING.value.floatValue();
+        int minX = xOffset + padding;
+        int maxX = this.width - padding - (xSize - xOffset);
+        int minY = yOffset + padding;
+        int maxY = this.height - padding - (ySize - yOffset);
+        int newX = MathHelper.clamp(mouseX, minX, Math.max(minX, maxX));
+        int newY = MathHelper.clamp(mouseY, minY, Math.max(minY, maxY));
 
         Layout layout = this.heldComponent.getLayout();
         if (layout instanceof LayoutAbsolute absoluteLayout) {
-            absoluteLayout.setXPosition((float) newX / this.width);
-            absoluteLayout.setYPosition((float) newY / this.height);
+            int usableWidth = Math.max(1, this.width - padding * 2);
+            int usableHeight = Math.max(1, this.height - padding * 2);
+            absoluteLayout.setXPosition((float) (newX - padding) / usableWidth);
+            absoluteLayout.setYPosition((float) (newY - padding) / usableHeight);
         }
 
         int snapRadius = 10;
@@ -638,7 +648,9 @@ public class ScreenHudEditor extends Screen {
             }
 
             if (!didSnap) {
-                LayoutAbsolute newLayout = new LayoutAbsolute((float) newX / this.width, (float) newY / this.height, this.heldAnchor);
+                int usableWidth = Math.max(1, this.width - padding * 2);
+                int usableHeight = Math.max(1, this.height - padding * 2);
+                LayoutAbsolute newLayout = new LayoutAbsolute((float) (newX - padding) / usableWidth, (float) (newY - padding) / usableHeight, this.heldAnchor);
                 ((HudComponentMovable) this.heldComponent).setLayout(newLayout);
                 this.snappedComponent = null;
                 this.snappedAnchor = null;
@@ -681,10 +693,13 @@ public class ScreenHudEditor extends Screen {
     private ComponentAnchor getScreenAnchorInRadius(int x, int y, int mouseX, int mouseY, int radius) {
         ComponentAnchor anchor = null;
         int minDistance = Integer.MAX_VALUE;
+        int padding = (int) GameSettings.SCREEN_PADDING.value.floatValue();
+        int usableWidth = Math.max(1, this.width - padding * 2);
+        int usableHeight = Math.max(1, this.height - padding * 2);
         for (ComponentAnchor componentAnchor : ComponentAnchor.values()) {
             if (componentAnchor == ComponentAnchor.CENTER) continue;
-            int xAnchor = (int) (componentAnchor.xPosition * this.width);
-            int yAnchor = (int) (componentAnchor.yPosition * this.height);
+            int xAnchor = padding + (int) (componentAnchor.xPosition * usableWidth);
+            int yAnchor = padding + (int) (componentAnchor.yPosition * usableHeight);
             int distance = (int) Math.sqrt(Math.pow(mouseX - (x + xAnchor), 2) + Math.pow(mouseY - (y + yAnchor), 2));
             if (distance < minDistance && distance <= radius) {
                 minDistance = distance;
@@ -720,7 +735,7 @@ public class ScreenHudEditor extends Screen {
             if (!component.isEnabled()) continue;
             Layout layout = component.getLayout();
             GLRenderer.pushFrame();
-            component.renderPreview(this, layout, this.width, this.height);
+            component.renderPreviewScaled(this, layout, this.width, this.height);
             GLRenderer.popFrame();
 
             if (component == this.selectedComponent && (!this.isDragging || component != this.heldComponent)) {
@@ -756,7 +771,7 @@ public class ScreenHudEditor extends Screen {
         if (this.heldComponent != null && this.isDragging) {
             Layout layout = this.heldComponent.getLayout();
             GLRenderer.pushFrame();
-            this.heldComponent.renderPreview(this, layout, this.width, this.height);
+            this.heldComponent.renderPreviewScaled(this, layout, this.width, this.height);
             GLRenderer.popFrame();
             int x = layout.getComponentX(this.heldComponent, this.width);
             int y = layout.getComponentY(this.heldComponent, this.height);
@@ -774,6 +789,13 @@ public class ScreenHudEditor extends Screen {
             int xAnchor = this.snappedComponent.getDisplayedAnchorX(this.snappedAnchor);
             int yAnchor = this.snappedComponent.getDisplayedAnchorY(this.snappedAnchor);
             drawAnchor(x, y, xAnchor, yAnchor, this.snappedAnchor);
+        } else if (this.heldComponent != null && this.isDragging && this.snappedAnchor != null) {
+            int padding = (int) GameSettings.SCREEN_PADDING.value.floatValue();
+            int usableWidth = Math.max(1, this.width - padding * 2);
+            int usableHeight = Math.max(1, this.height - padding * 2);
+            int xAnchor = (int) (this.snappedAnchor.xPosition * usableWidth);
+            int yAnchor = (int) (this.snappedAnchor.yPosition * usableHeight);
+            drawAnchor(padding, padding, xAnchor, yAnchor, this.snappedAnchor);
         }
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/chat/ScreenChat.java b/game/client/src/main/java/net/minecraft/client/gui/chat/ScreenChat.java
index 708b0f6d4..94e1074de 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/chat/ScreenChat.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/chat/ScreenChat.java
@@ -3,10 +3,12 @@ package net.minecraft.client.gui.chat;
 import com.mojang.logging.LogUtils;
 import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.hud.component.ComponentAnchor;
+import net.minecraft.client.gui.hud.component.HudComponents;
 import net.minecraft.client.gui.keyboard.ScreenKeyboard;
 import net.minecraft.client.gui.text.TextFieldEditor;
 import net.minecraft.client.input.InputType;
 import net.minecraft.client.option.GameSettings;
+import net.minecraft.client.render.renderer.GLRenderer;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.net.ChatEmotes;
 import org.lwjgl.input.Keyboard;
@@ -48,8 +50,8 @@ public class ScreenChat extends Screen implements ITextField {
                 this.mc,
                 this.editor,
 				this,
-				(parent, child, minecraft, followParameters) -> 16 + (followParameters ? this.suggestionsElement.getDefaultParameterPosition() - 1 : 0),
-				(parent, child, minecraft, followParameters) -> minecraft.resolution.getScaledHeightScreenCoords() - 14,
+				(parent, child, minecraft, followParameters) -> HudComponents.CHAT_INPUT.getLayout().getComponentX(HudComponents.CHAT_INPUT, minecraft.resolution.getScaledWidthScreenCoords()) + 14 + (followParameters ? this.suggestionsElement.getDefaultParameterPosition() - 1 : 0),
+				(parent, child, minecraft, followParameters) -> HudComponents.CHAT_INPUT.getLayout().getComponentY(HudComponents.CHAT_INPUT, minecraft.resolution.getScaledHeightScreenCoords()) - 2,
 				ComponentAnchor.BOTTOM_LEFT
 			);
 			if (!this.getText().startsWith("/")) {
@@ -80,7 +82,7 @@ public class ScreenChat extends Screen implements ITextField {
 	@Override
 	public void removed() {
 		Keyboard.enableRepeatEvents(false);
-        this.mc.hudIngame.chatScroll = 0;
+        HudComponents.CHAT.chatScroll = 0;
 	}
 
 	@Override
@@ -98,7 +100,7 @@ public class ScreenChat extends Screen implements ITextField {
 				if (this.showEmotePicker) {
                     this.emotePicker.scrollOffset((int)(-dWheel / 0.1f));
 				} else {
-                    this.mc.hudIngame.chatScroll += dWheel;
+                    HudComponents.CHAT.chatScroll += dWheel;
 				}
 			}
 
@@ -204,23 +206,41 @@ public class ScreenChat extends Screen implements ITextField {
 	@Override
 	public void render(int mx, int my, float partialTick) {
 		try {
+			int inputX = HudComponents.CHAT_INPUT.getLayout().getComponentX(HudComponents.CHAT_INPUT, this.width);
+			int inputY = HudComponents.CHAT_INPUT.getLayout().getComponentY(HudComponents.CHAT_INPUT, this.height);
+			float scale = HudComponents.CHAT_INPUT.getScale();
+			int boxWidth = HudComponents.CHAT_INPUT.getBaseXSize();
+
+			// Convert mouse coords to component-local (unscaled) space for hit-testing.
+			int localMx = unscaleX(mx, inputX, scale);
+			int localMy = unscaleY(my, inputY, scale);
+
 			// Draw emote picker button
 			int emotePickerButtonColor = 0x80000000;
 			int emotePickerTextColor = 0xE0E0E0;
-			if (mx >= 2 && mx < 14 && my >= this.height - 14 && my < this.height - 2)
+			if (localMx >= inputX && localMx < inputX + 12 && localMy >= inputY && localMy < inputY + 12)
 			{
 				emotePickerButtonColor = 0x80ffffff;
 				emotePickerTextColor = 0xffffffa0;
 			}
-			drawRect(2, this.height - 14, 14, this.height - 2, emotePickerButtonColor);
-			drawStringCenteredShadow(this.fontRenderer, Character.toString('\u263a'), 2 + 6, this.height - 12, emotePickerTextColor);
 
-			drawRect(16, this.height - 14, this.width - 2, this.height - 2, 0x80000000);
+			boolean scaled = scale != 1.0f;
+			if (scaled) {
+				GLRenderer.pushFrame();
+				GLRenderer.modelM4f().translate(inputX, inputY, 0.0f);
+				GLRenderer.modelM4f().scale(scale, scale, 1.0f);
+				GLRenderer.modelM4f().translate(-inputX, -inputY, 0.0f);
+			}
+
+			drawRect(inputX, inputY, inputX + 12, inputY + 12, emotePickerButtonColor);
+			drawStringCenteredShadow(this.fontRenderer, Character.toString('\u263a'), inputX + 6, inputY + 2, emotePickerTextColor);
+
+			drawRect(inputX + 14, inputY, inputX + boxWidth, inputY + 12, 0x80000000);
 
-			drawStringShadow(this.fontRenderer, this.suggestionsElement.getSuggestionPreview(), 16 + this.suggestionsElement.getDefaultParameterPosition(), this.mc.resolution.getScaledHeightScreenCoords() - 12, 0xFFFFFF);
+			drawStringShadow(this.fontRenderer, this.suggestionsElement.getSuggestionPreview(), inputX + 14 + this.suggestionsElement.getDefaultParameterPosition(), inputY + 2, 0xFFFFFF);
 			boolean drawCursor = (this.updateCounter / 6) % 2 == 0;
 			int cursor = this.editor.getCursor();
-			drawStringShadow(this.fontRenderer, this.suggestionsElement.colorCodeText(this.message, true), 18, this.height - 12, 0xE0E0E0);
+			drawStringShadow(this.fontRenderer, this.suggestionsElement.colorCodeText(this.message, true), inputX + 16, inputY + 2, 0xE0E0E0);
 			if (drawCursor)
 			{
 				int width = MathHelper.ceil(this.fontRenderer.stringWidthDouble(this.message));
@@ -228,11 +248,15 @@ public class ScreenChat extends Screen implements ITextField {
 				{
 					width = MathHelper.ceil(this.fontRenderer.stringWidthDouble(this.message.substring(0, cursor)));
 				}
-				drawStringShadow(this.fontRenderer, "_", 18 + width, this.height - 12, 0xE0E0E0);
+				drawStringShadow(this.fontRenderer, "_", inputX + 16 + width, inputY + 2, 0xE0E0E0);
 			}
 
 			if (this.showEmotePicker) {
-                this.emotePicker.draw(2, this.height - 16 - this.emotePicker.getHeight(), mx, my);
+                this.emotePicker.draw(inputX, inputY - 2 - this.emotePicker.getHeight(), localMx, localMy);
+			}
+
+			if (scaled) {
+				GLRenderer.popFrame();
 			}
 
 			super.render(mx, my, partialTick);
@@ -244,18 +268,34 @@ public class ScreenChat extends Screen implements ITextField {
 		}
 	}
 
+	private static int unscaleX(int screenX, int anchorX, float scale) {
+		if (scale == 1.0f) return screenX;
+		return Math.round(anchorX + (screenX - anchorX) / scale);
+	}
+
+	private static int unscaleY(int screenY, int anchorY, float scale) {
+		if (scale == 1.0f) return screenY;
+		return Math.round(anchorY + (screenY - anchorY) / scale);
+	}
+
 	@Override
 	public void mouseClicked(int mx, int my, int buttonNum) {
 		super.mouseClicked(mx, my, buttonNum);
 		try {
 			boolean handled = false;
 			if (buttonNum == 0) {
-				if (mx >= 2 && mx < 14 && my >= this.height - 14 && my < this.height - 2) {
+				int inputX = HudComponents.CHAT_INPUT.getLayout().getComponentX(HudComponents.CHAT_INPUT, this.width);
+				int inputY = HudComponents.CHAT_INPUT.getLayout().getComponentY(HudComponents.CHAT_INPUT, this.height);
+				float scale = HudComponents.CHAT_INPUT.getScale();
+				int localMx = unscaleX(mx, inputX, scale);
+				int localMy = unscaleY(my, inputY, scale);
+
+				if (localMx >= inputX && localMx < inputX + 12 && localMy >= inputY && localMy < inputY + 12) {
                     this.showEmotePicker = !this.showEmotePicker;
 					handled = true;
 				}
 				if (!handled && this.showEmotePicker) {
-					Character c = this.emotePicker.click(mx - 2, my - (this.height - 16 - this.emotePicker.getHeight()));
+					Character c = this.emotePicker.click(localMx - inputX, localMy - (inputY - 2 - this.emotePicker.getHeight()));
 					if (c != null) {
                         this.editor.handleInput(0, c);
 						if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT))
diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventory.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventory.java
index f2dc21dbc..e89aa4ef6 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventory.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventory.java
@@ -270,6 +270,7 @@ public class ScreenInventory extends ScreenContainerAbstract {
         float eyesY = (float) ((y + 75) - 50) - this.ySize_lo;
         GLRenderer.modelM4f().rotateY(org.joml.Math.toRadians(135F));
         Lighting.enableLight();
+        GLRenderer.setLightMapStrength(0f);
         GLRenderer.modelM4f().rotateY(org.joml.Math.toRadians(-135F));
         GLRenderer.modelM4f().rotateX(org.joml.Math.toRadians(-(float) Math.atan(eyesY / 40F) * 20F));
         this.mc.thePlayer.yBodyRotO = this.mc.thePlayer.yBodyRot = (float) Math.atan(eyesX / 40F) * 20F;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventoryCreative.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventoryCreative.java
index 79e1c3ed6..90b1e8cdb 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventoryCreative.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventoryCreative.java
@@ -12,6 +12,8 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.client.gui.options.OptionsButtonElement;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.player.inventory.menu.MenuInventoryCreative;
+import net.minecraft.core.util.helper.MathHelper;
+import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.render.Lighting;
 import net.minecraft.client.render.EntityRendererDispatcher;
 import org.jetbrains.annotations.NotNull;
@@ -47,12 +49,25 @@ public class ScreenInventoryCreative extends ScreenInventory implements ITextCha
         this.searchField.drawBackground = false;
         this.searchField.setMaxStringLength(14);
         this.searchField.setTextChangeListener(this);
+        this.applySavedCreativeInventoryPage();
         updatePageSwitcher();
         Keyboard.enableRepeatEvents(true);
     }
 
     public void scroll(int direction) {
-        if (direction == 0) return;
+        if (direction == 0) {
+            return;
+        }
+        final boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
+        if (shift) {
+            if (direction > 0 && this.container.page > 0) {
+                this.container.jumpToFirstCreativePage();
+            } else if (direction < 0 && this.container.page < this.container.maxPage) {
+                this.container.jumpToLastCreativePage();
+            }
+            updatePageSwitcher();
+            return;
+        }
         int count = 1;
         if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) {
             count = 10;
@@ -62,24 +77,25 @@ public class ScreenInventoryCreative extends ScreenInventory implements ITextCha
         }
         while (this.lastPageButton.enabled && direction > 0 && count > 0) {
             this.container.lastPage();
-            updatePageSwitcher();
             count--;
         }
         while (this.nextPageButton.enabled && direction < 0 && count > 0) {
             this.container.nextPage();
-            updatePageSwitcher();
             count--;
         }
+        updatePageSwitcher();
     }
 
     @Override
     public void tick() {
         super.tick();
         this.searchField.updateCursorCounter();
+        this.updateCreativePageArrowLabels();
     }
 
     @Override
     public void removed() {
+        this.persistCreativeInventoryPage();
         super.removed();
         Keyboard.enableRepeatEvents(false);
     }
@@ -89,6 +105,26 @@ public class ScreenInventoryCreative extends ScreenInventory implements ITextCha
         this.nextPageButton.enabled = this.container.page != this.container.maxPage;
 
         this.pageString = (this.container.page + 1) + "/" + (this.container.maxPage + 1);
+        this.persistCreativeInventoryPage();
+    }
+
+    private void applySavedCreativeInventoryPage() {
+        final int saved = GameSettings.LAST_CREATIVE_INVENTORY_PAGE.value;
+        final int maxPage = this.container.maxPage;
+        final int clamped = MathHelper.clamp(saved, 0, maxPage);
+        if (clamped != saved) {
+            GameSettings.LAST_CREATIVE_INVENTORY_PAGE.set(clamped);
+            GameSettings.saveOptions();
+        }
+        this.container.setInventoryStatus(clamped, this.container.searchText);
+    }
+
+    private void persistCreativeInventoryPage() {
+        final int page = this.container.page;
+        if (page != GameSettings.LAST_CREATIVE_INVENTORY_PAGE.value) {
+            GameSettings.LAST_CREATIVE_INVENTORY_PAGE.set(page);
+            GameSettings.saveOptions();
+        }
     }
 
     @Override
@@ -99,9 +135,17 @@ public class ScreenInventoryCreative extends ScreenInventory implements ITextCha
         }
 
         if (button == this.lastPageButton) {
-            scroll(1);
+            if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
+                this.container.jumpToFirstCreativePage();
+            } else {
+                scroll(1);
+            }
         } else if (button == this.nextPageButton) {
-            scroll(-1);
+            if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
+                this.container.jumpToLastCreativePage();
+            } else {
+                scroll(-1);
+            }
         } else if (button == this.clearSearchButton) {
             if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
                 for (int i = 0; i < this.container.inventory.getContainerSize() + this.container.craftSlots.getContainerSize() + this.container.resultSlots.getContainerSize(); i++) {
@@ -184,6 +228,7 @@ public class ScreenInventoryCreative extends ScreenInventory implements ITextCha
         float eyesY = (float) ((y + 75) - 50) - this.ySize_lo;
         GLRenderer.modelM4f().rotateY(org.joml.Math.toRadians(135F));
         Lighting.enableLight();
+        GLRenderer.setLightMapStrength(0f);
         GLRenderer.modelM4f().rotateY(org.joml.Math.toRadians(-135F));
         GLRenderer.modelM4f().rotateX(org.joml.Math.toRadians(-(float) Math.atan(eyesY / 40F) * 20F));
         this.mc.thePlayer.yBodyRotO = this.mc.thePlayer.yBodyRot = (float) Math.atan(eyesX / 40F) * 20F;
@@ -213,6 +258,12 @@ public class ScreenInventoryCreative extends ScreenInventory implements ITextCha
         updatePageSwitcher();
     }
 
+    private void updateCreativePageArrowLabels() {
+        final boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
+        this.lastPageButton.displayString = shift ? "|<" : "<";
+        this.nextPageButton.displayString = shift ? ">|" : ">";
+    }
+
     @Override
     public void guiSpecificControllerInput(@NotNull ControllerInput controller) {
         if (controller.buttonLeftShoulder.pressedThisFrame()) {
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 579acb765..51ae70bf7 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
@@ -61,7 +61,6 @@ import org.slf4j.Logger;
 
 public class HudIngame extends Gui {
     public static final float DEBUG_SCALE = 1f;
-    public static final int MAX_CHAT_WIDTH = 320;
     private static final Logger LOGGER = LogUtils.getLogger();
     public static final Direction[] directions = new Direction[]{Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST};
 
@@ -70,7 +69,6 @@ public class HudIngame extends Gui {
     private static final float ACID_OVERLAY_LERP_UP = 0.13F;
     private static final float ACID_OVERLAY_LERP_DOWN = 0.038F;
 
-    private final @NotNull List<@NotNull ChatLine> chatMessageList = new ArrayList<>();
     protected Minecraft mc;
     public int updateCounter = 0;
     private String recordPlaying = "";
@@ -81,7 +79,6 @@ public class HudIngame extends Gui {
     protected float acidOverlayAlpha;
     protected float acidImmersionRamp;
     protected FontRenderer fontRenderer;
-    public int chatScroll = 0;
 
 
     public HudIngame(Minecraft minecraft) {
@@ -122,7 +119,7 @@ public class HudIngame extends Gui {
         for (final HudComponent component : HudComponents.INSTANCE.getComponents()) {
             if (component.isVisible()) {
                 GLRenderer.pushFrame();
-                component.render(this, width, height, partialTicks);
+                component.renderScaled(this, width, height, partialTicks);
                 GLRenderer.popFrame();
             }
         }
@@ -395,10 +392,6 @@ public class HudIngame extends Gui {
             }
         }
 
-        if (GameSettings.IMMERSIVE_MODE.drawChat()) {
-            drawChat(width, height);
-        }
-
         // Adding this mostly to see if the stitcher and dynamic textures are working properly
         if (GameSettings.KEY_TOGGLE_TEXTURE_ATLAS.isPressed()) {
             GLRenderer.pushFrame();
@@ -563,63 +556,6 @@ public class HudIngame extends Gui {
         }
     }
 
-    public void drawChat(int width, int height) {
-        if (GameSettings.chatVisibility.value == ChatVisibility.NEVER_SHOW) return;
-//        if(mc.currentScreen instanceof ScreenChat && ((ScreenChat) mc.currentScreen).message.startsWith("/")) return;
-        int linesToShow = 10;
-        boolean ignoreFadeout = false;
-        if (this.mc.currentScreen instanceof ScreenChat) {
-            int acceptableSize = height - 48 - 48;
-            linesToShow = acceptableSize / 9;
-            ignoreFadeout = true;
-        } else if (GameSettings.chatVisibility.value == ChatVisibility.SHOW_WHEN_CHATTING) {
-            return;
-        }
-
-        if (this.chatScroll > this.chatMessageList.size() - linesToShow)
-            this.chatScroll = this.chatMessageList.size() - linesToShow;
-        if (this.chatScroll < 0) this.chatScroll = 0;
-
-        GLRenderer.enableState(State.BLEND);
-        GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
-        GLRenderer.pushFrame();
-        GLRenderer.modelM4f().translate(0.0F, height - 48, 0.0F);
-        int y = -12;
-        for (int i = 0; i < linesToShow; i++) {
-            if (this.chatScroll + i >= this.chatMessageList.size()) continue;
-            final ChatLine line = this.chatMessageList.get(this.chatScroll + i);
-            if (line.updateCounter >= 190 && !ignoreFadeout) {
-                continue;
-            }
-            double fadeAmount = (double) line.updateCounter / 200D;
-            fadeAmount = 1.0D - fadeAmount;
-            fadeAmount *= 10D;
-            if (fadeAmount < 0.0D) {
-                fadeAmount = 0.0D;
-            }
-            if (fadeAmount > 1.0D) {
-                fadeAmount = 1.0D;
-            }
-            fadeAmount *= fadeAmount;
-            int alpha = (int) (255D * fadeAmount);
-            if (ignoreFadeout) {
-                alpha = 255;
-            }
-            if (alpha > 0) {
-                final CharSequence message = line.message;
-                final byte xPad = 2;
-                final int h = MathHelper.ceil(this.fontRenderer.heightOfConstrainedChars(message, MAX_CHAT_WIDTH));
-                y -= (h + 2);
-                drawRect(xPad, y - 1, xPad + MAX_CHAT_WIDTH, y + h + 1, alpha / 2 << 24);
-                GLRenderer.enableState(State.BLEND);
-                this.fontRenderer.renderWidthConstrained(message, xPad, y, MAX_CHAT_WIDTH).setShadow().setColor(0xFFFFFF + (alpha << 24)).call();
-            }
-        }
-
-        GLRenderer.popFrame();
-        GLRenderer.disableState(State.BLEND);
-    }
-
     public static String getTimeString(Minecraft mc) {
         long worldTime = mc.currentWorld.getWorldTime();
         int dayLength = Global.DAY_LENGTH_TICKS;
@@ -772,22 +708,16 @@ public class HudIngame extends Gui {
             this.recordPlayingUpFor--;
         }
         this.updateCounter++;
-        for (ChatLine chatLine : this.chatMessageList) {
-            chatLine.updateCounter++;
-        }
-
+        HudComponents.CHAT.updateTick();
     }
 
     public void clearChatMessages() {
-        this.chatMessageList.clear();
+        HudComponents.CHAT.clearChatMessages();
     }
 
     public void addChatMessage(final CharSequence s) {
         LOGGER.info("[CHAT] {}", s);
-        this.chatMessageList.add(0, new ChatLine(s));
-        while (this.chatMessageList.size() > 100) {
-            this.chatMessageList.remove(this.chatMessageList.size() - 1);
-        }
+        HudComponents.CHAT.addChatMessage(s);
     }
 
     public void setRecordPlayingMessage(String s) {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponent.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponent.java
index b21e0784a..6b089a1da 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponent.java
@@ -1,18 +1,24 @@
 package net.minecraft.client.gui.hud.component;
 
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.ScaledResolution;
 import net.minecraft.client.gui.Gui;
 import net.minecraft.client.gui.ScreenHudEditor;
 import net.minecraft.client.gui.hud.HudIngame;
 import net.minecraft.client.gui.hud.component.layout.LayoutAbsolute;
 import net.minecraft.client.gui.hud.component.layout.Layout;
 import net.minecraft.client.gui.hud.component.layout.LayoutSnap;
+import net.minecraft.client.gui.options.components.BooleanToggleComponent;
 import net.minecraft.client.gui.options.components.KeyBindingComponent;
 import net.minecraft.client.gui.options.components.OptionsComponent;
+import net.minecraft.client.gui.options.components.ToggleableOptionComponent;
+import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.option.KeyBinding;
 import net.minecraft.client.option.Option;
+import net.minecraft.client.option.OptionGuiScaleOverride;
 import net.minecraft.client.render.renderer.GLRenderer;
 import net.minecraft.client.render.renderer.State;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -33,11 +39,71 @@ public abstract class HudComponent {
 
     Layout layout;
 
+    private boolean snapToFill = true;
+    private static final boolean DEFAULT_SNAP_TO_FILL = true;
+    private OptionGuiScaleOverride guiScaleOverride = new OptionGuiScaleOverride();
+
     public HudComponent(String key, int xSize, int ySize, Layout layout) {
         this.key = key;
         this.xSize = xSize;
         this.ySize = ySize;
         this.layout = layout;
+
+        addDefaultOptionSuppliers();
+    }
+
+    protected void addDefaultOptionSuppliers() {
+        this.optionComponentSuppliers.add(() -> new BooleanToggleComponent(
+            "gui.options.hudeditor.snap_to_fill",
+            DEFAULT_SNAP_TO_FILL,
+            this::isSnapToFill,
+            this::setSnapToFill
+        ));
+
+        this.optionComponentSuppliers.add(() -> new ToggleableOptionComponent<>(
+            this.getGuiScaleOverrideOption()
+        ).applyOnRelease());
+    }
+
+    public boolean isSnapToFill() {
+        return this.snapToFill;
+    }
+
+    public void setSnapToFill(boolean snapToFill) {
+        this.snapToFill = snapToFill;
+    }
+
+    public OptionGuiScaleOverride getGuiScaleOverrideOption() {
+        return this.guiScaleOverride;
+    }
+
+    protected void setGuiScaleOverrideOption(OptionGuiScaleOverride override) {
+        this.guiScaleOverride = override;
+    }
+
+    public int getScaleOverride() {
+        return this.getGuiScaleOverrideOption().value;
+    }
+
+    public void setScaleOverride(int value) {
+        this.getGuiScaleOverrideOption().value = Math.max(0, value);
+    }
+
+    public static int getEffectiveGlobalScale() {
+        int v = GameSettings.GUI_SCALE.value;
+        if (v > 0) return v;
+        return ScaledResolution.getMaxScale(
+            mc.gameWindow.getWidthScreenCoords(),
+            mc.gameWindow.getHeightScreenCoords()
+        );
+    }
+
+    public float getScale() {
+        int override = getScaleOverride();
+        if (override <= 0) return 1.0f;
+        int global = getEffectiveGlobalScale();
+        if (global <= 0) return 1.0f;
+        return (float) override / (float) global;
     }
 
     public abstract boolean isVisible();
@@ -61,37 +127,51 @@ public abstract class HudComponent {
         return key;
     }
 
+    /**
+     * Returns the base (unscaled) horizontal size of the component.
+     */
+    public int getBaseXSize() {
+        return xSize;
+    }
+
+    /**
+     * Returns the base (unscaled) vertical size of the component.
+     */
+    public int getBaseYSize() {
+        return ySize;
+    }
+
     public int getDisplayedXSize() {
         if (!isEnabled() || (!(mc.currentScreen instanceof ScreenHudEditor) && !isVisible())) return 0;
-        return xSize;
+        return Math.round(getBaseXSize() * getScale());
     }
 
     public int getDisplayedYSize() {
         if (!isEnabled() || (!(mc.currentScreen instanceof ScreenHudEditor) && !isVisible())) return 0;
-        return ySize;
+        return Math.round(getBaseYSize() * getScale());
     }
 
-    public int getDisplayedAnchorX(ComponentAnchor anchor) {
+    public int getDisplayedAnchorX(@NotNull ComponentAnchor anchor) {
         return (int) (anchor.xPosition * this.getDisplayedXSize());
     }
 
-    public int getDisplayedAnchorY(ComponentAnchor anchor) {
+    public int getDisplayedAnchorY(@NotNull ComponentAnchor anchor) {
         return (int) (anchor.yPosition * this.getDisplayedYSize());
     }
 
     public int getTrueXSize() {
-        return xSize;
+        return Math.round(getBaseXSize() * getScale());
     }
 
     public int getTrueYSize() {
-        return ySize;
+        return Math.round(getBaseYSize() * getScale());
     }
 
-    public int getTrueAnchorX(ComponentAnchor anchor) {
+    public int getTrueAnchorX(@NotNull ComponentAnchor anchor) {
         return (int) (anchor.xPosition * this.getTrueXSize());
     }
 
-    public int getTrueAnchorY(ComponentAnchor anchor) {
+    public int getTrueAnchorY(@NotNull ComponentAnchor anchor) {
         return (int) (anchor.yPosition * this.getTrueYSize());
     }
 
@@ -117,6 +197,10 @@ public abstract class HudComponent {
         return this.optionComponentSuppliers;
     }
 
+    protected void addOptionComponentSupplier(Supplier<OptionsComponent> supplier) {
+        this.optionComponentSuppliers.add(supplier);
+    }
+
     public List<Supplier<KeyBindingComponent>> getKeyBindingSuppliers() {
         return this.keyBindingComponentSuppliers;
     }
@@ -133,7 +217,41 @@ public abstract class HudComponent {
 
     public abstract void renderPreview(Gui gui, Layout layout, int xSizeScreen, int ySizeScreen);
 
-    public final String toSettingsString() {
+    /**
+     * Renders the component, applying the per-component scale via a GL transform.
+     */
+    public final void renderScaled(HudIngame hud, int xSizeScreen, int ySizeScreen, float partialTick) {
+        float scale = getScale();
+        if (scale == 1.0f) {
+            render(hud, xSizeScreen, ySizeScreen, partialTick);
+            return;
+        }
+        int x = this.layout.getComponentX(this, xSizeScreen);
+        int y = this.layout.getComponentY(this, ySizeScreen);
+        GLRenderer.modelM4f().translate(x, y, 0.0f);
+        GLRenderer.modelM4f().scale(scale, scale, 1.0f);
+        GLRenderer.modelM4f().translate(-x, -y, 0.0f);
+        render(hud, xSizeScreen, ySizeScreen, partialTick);
+    }
+
+    /**
+     * Renders the preview, applying the per-component scale via a GL transform.
+     */
+    public final void renderPreviewScaled(Gui gui, Layout layout, int xSizeScreen, int ySizeScreen) {
+        float scale = getScale();
+        if (scale == 1.0f) {
+            renderPreview(gui, layout, xSizeScreen, ySizeScreen);
+            return;
+        }
+        int x = layout.getComponentX(this, xSizeScreen);
+        int y = layout.getComponentY(this, ySizeScreen);
+        GLRenderer.modelM4f().translate(x, y, 0.0f);
+        GLRenderer.modelM4f().scale(scale, scale, 1.0f);
+        GLRenderer.modelM4f().translate(-x, -y, 0.0f);
+        renderPreview(gui, layout, xSizeScreen, ySizeScreen);
+    }
+
+    public final @NotNull String toSettingsString() {
         String layoutString;
         if (layout instanceof LayoutAbsolute) {
             layoutString = "abs";
@@ -142,10 +260,13 @@ public abstract class HudComponent {
         } else {
             throw new RuntimeException("Unknown layout type: " + layout.getClass().getName());
         }
-        return key + "{[" + toSettingsParametersString() + "];" + layoutString + "[" + layout.toSettingsString() + "]}";
+        return key + "{[" + toSettingsParametersString() + "];"
+            + layoutString + "[" + layout.toSettingsString() + "];"
+            + "fill[" + this.snapToFill + "];"
+            + "override[" + this.getScaleOverride() + "]}";
     }
 
-    public final void fromSettingsString(String settings) {
+    public final void fromSettingsString(@NotNull String settings) {
         String[] parts = settings.split(";");
         String parameters = parts[0].substring(1, parts[0].length() - 1);
         fromSettingsParametersString(parameters);
@@ -159,6 +280,25 @@ public abstract class HudComponent {
             throw new RuntimeException("Unknown layout type: " + layoutString);
         }
         layout.fromSettingsString(layoutSettings);
+
+        this.snapToFill = DEFAULT_SNAP_TO_FILL;
+        this.setScaleOverride(0);
+        for (int i = 2; i < parts.length; i++) {
+            String part = parts[i];
+            int bracketStart = part.indexOf('[');
+            if (bracketStart < 0) continue;
+            String name = part.substring(0, bracketStart);
+            String value = part.substring(bracketStart + 1, part.endsWith("}") ? part.length() - 2 : part.length() - 1);
+            if (name.equals("fill")) {
+                this.snapToFill = Boolean.parseBoolean(value);
+            } else if (name.equals("override")) {
+                try {
+                    this.setScaleOverride(Integer.parseInt(value));
+                } catch (NumberFormatException ignored) {
+                    this.setScaleOverride(0);
+                }
+            }
+        }
     }
 
     protected String toSettingsParametersString() {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentChat.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentChat.java
new file mode 100644
index 000000000..665fac4a2
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentChat.java
@@ -0,0 +1,283 @@
+package net.minecraft.client.gui.hud.component;
+
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.hud.HudIngame;
+import net.minecraft.client.gui.hud.component.layout.Layout;
+import net.minecraft.client.gui.options.components.FloatSliderComponent;
+import net.minecraft.client.option.GameSettings;
+import net.minecraft.core.enums.ChatVisibility;
+import net.minecraft.client.render.font.FontRenderer;
+import net.minecraft.client.render.renderer.BlendFactor;
+import net.minecraft.client.render.renderer.GLRenderer;
+import net.minecraft.client.render.renderer.State;
+import net.minecraft.core.net.ChatLine;
+import net.minecraft.client.gui.chat.ScreenChat;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class HudComponentChat extends HudComponentMovable {
+    public static final int DEFAULT_CHAT_WIDTH = 220;
+    public static final int DEFAULT_CHAT_HEIGHT = 110;
+    public static final int MIN_CHAT_WIDTH = 80;
+    public static final int MAX_RESIZE_WIDTH = 600;
+    public static final int MIN_CHAT_HEIGHT = 30;
+    public static final int MAX_RESIZE_HEIGHT = 1000;
+    private static final int CHAT_PADDING = 2;
+    private static final int LINE_SPACING = 2;
+    public final @NotNull List<@NotNull ChatLine> chatMessageList = new ArrayList<>();
+    public int chatScroll = 0;
+
+    private int customWidth;
+    private int customHeight;
+
+    public HudComponentChat(String key, int xSize, int ySize, Layout layout) {
+        super(key, xSize, ySize, layout);
+        this.customWidth = xSize;
+        this.customHeight = ySize;
+
+        setSnapToFill(false);
+
+        addOptionComponentSupplier(() -> new FloatSliderComponent(
+            "gui.options.hudeditor.chat_width",
+            DEFAULT_CHAT_WIDTH,
+            MIN_CHAT_WIDTH,
+            MAX_RESIZE_WIDTH,
+            () -> (float) this.customWidth,
+            value -> this.customWidth = Math.round(value),
+            value -> Math.round(value) + "px"
+        ));
+
+        addOptionComponentSupplier(() -> new FloatSliderComponent(
+            "gui.options.hudeditor.chat_height",
+            DEFAULT_CHAT_HEIGHT,
+            MIN_CHAT_HEIGHT,
+            MAX_RESIZE_HEIGHT,
+            () -> (float) this.customHeight,
+            value -> this.customHeight = Math.round(value),
+            value -> Math.round(value) + "px"
+        ));
+    }
+
+    @Override
+    public int getBaseXSize() {
+        return this.customWidth;
+    }
+
+    @Override
+    public int getBaseYSize() {
+        return this.customHeight;
+    }
+
+    @Override
+    protected String toSettingsParametersString() {
+        return "w=" + this.customWidth + ",h=" + this.customHeight;
+    }
+
+    @Override
+    protected void fromSettingsParametersString(String settings) {
+        if (settings == null || settings.isEmpty()) return;
+        for (String token : settings.split(",")) {
+            int eq = token.indexOf('=');
+            if (eq < 0) continue;
+            String key = token.substring(0, eq);
+            String value = token.substring(eq + 1);
+            try {
+                int parsed = Integer.parseInt(value);
+                if (key.equals("w")) {
+                    this.customWidth = MathHelper.clamp(parsed, MIN_CHAT_WIDTH, MAX_RESIZE_WIDTH);
+                } else if (key.equals("h")) {
+                    this.customHeight = MathHelper.clamp(parsed, MIN_CHAT_HEIGHT, MAX_RESIZE_HEIGHT);
+                }
+            } catch (NumberFormatException ignored) {}
+        }
+    }
+
+    @Override
+    public boolean isVisible() {
+        if (GameSettings.chatVisibility.value == ChatVisibility.NEVER_SHOW) return false;
+        if (!GameSettings.IMMERSIVE_MODE.drawChat()) return false;
+        return GameSettings.chatVisibility.value != ChatVisibility.SHOW_WHEN_CHATTING || mc.currentScreen instanceof ScreenChat;
+    }
+
+    @Override
+    public void render(HudIngame hud, int xSizeScreen, int ySizeScreen, float partialTick) {
+        drawChat(hud, xSizeScreen, ySizeScreen);
+    }
+
+    @Override
+    public boolean isPreviewTranslucent() {
+        return !isVisible();
+    }
+
+    @Override
+    public void renderPreview(Gui gui, @NotNull Layout layout, int xSizeScreen, int ySizeScreen) {
+
+        renderTranslucency();
+
+        int x = layout.getComponentX(this, xSizeScreen);
+        int y = layout.getComponentY(this, ySizeScreen);
+
+        List<String> previews = Arrays.asList(
+            "<Scratchylongnose> Hello, and welcome!",
+            "<EthosRoom> Look at all those chickens..",
+            "<ModernBeef> Who knows where the basalt farm is?",
+            "<JumboHumbo> A little overengineered I guess..",
+            "<CaptainSunshine> Creeper! Aww man..",
+            "<DriftySpawners> Starting a fresh build at spawn tonight.",
+            "<MildFruitDrink> So uhh.. when are melons getting added?",
+            "<MasterCaver> I catalogued every ore vein in this cave.",
+            "<NoSenseOfDirection> Uhh, I'm a bit lost... this server have TPA?",
+            "<CreeperCrazy> they always move left... I SWEAR THEY DO BELIEVE ME!",
+            "<TorchRunner> Lighting up this whole mountain by hand.",
+            "<ClayFarmer> Sorry this river is out of clay.",
+            "<RailSmith> New nether hub is opening soon",
+            "<RedstoneRambler> Hey come take a look at this 0t cobble farm!",
+            "<MapMaker> [Doesn't exist]",
+            "<DiamondDaisy> Like actually, genuine 16 MEGA VEIN the other day",
+            "<PistonPoet> Look all I'm saying is doors should feel dramatic when they open.",
+            "<BuilderBea> Need opinions on this roof gradient.",
+            "<FarlandsFan> Almost there...",
+            "<WoolWizard> Sheep colors are sorted, labeled, and currently farming.",
+            "<OceanOtto> Yeah I'm never draining any ocean again, get me out of here.",
+            "<Herobrine> Really, a herobrine reference in BTA? Ugh."
+        );
+        drawLines(gui, mc.font, previews, x, y, 255);
+    }
+
+    public void updateTick() {
+        for (ChatLine chatLine : this.chatMessageList) {
+            chatLine.updateCounter++;
+        }
+    }
+
+    public void clearChatMessages() {
+        this.chatMessageList.clear();
+    }
+
+    public void addChatMessage(final CharSequence s) {
+        this.chatMessageList.add(0, new ChatLine(s));
+        while (this.chatMessageList.size() > 100) {
+            this.chatMessageList.remove(this.chatMessageList.size() - 1);
+        }
+    }
+
+    private int getMessageWrapWidth() {
+        return Math.max(1, this.customWidth - (CHAT_PADDING * 2));
+    }
+
+    private void drawChat(HudIngame hud, int xSizeScreen, int ySizeScreen) {
+        int x = this.getLayout().getComponentX(this, xSizeScreen);
+        int y = this.getLayout().getComponentY(this, ySizeScreen);
+
+        int wrapWidth = getMessageWrapWidth();
+        int singleLineHeight = 9 + LINE_SPACING;
+        int linesToShow = Math.max(1, (this.customHeight - CHAT_PADDING * 2) / singleLineHeight);
+        boolean ignoreFadeout = false;
+        if (mc.currentScreen instanceof ScreenChat) {
+            int acceptableSize = ySizeScreen - 48 - 48;
+            linesToShow = Math.max(linesToShow, acceptableSize / singleLineHeight);
+            ignoreFadeout = true;
+        }
+
+        if (this.chatScroll > this.chatMessageList.size() - linesToShow)
+            this.chatScroll = this.chatMessageList.size() - linesToShow;
+        if (this.chatScroll < 0) this.chatScroll = 0;
+
+        GLRenderer.enableState(State.BLEND);
+        GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
+
+        int linesUsed = Math.min(linesToShow, this.chatMessageList.size() - this.chatScroll);
+        int totalHeight = computeTotalHeight(this.chatMessageList, this.chatScroll, linesUsed, ignoreFadeout, wrapWidth);
+
+        float yMult = GameSettings.VERTICAL_CHAT_TEXT_ALIGNMENT.value.multiplier;
+        int alignmentSpace = this.getBaseYSize() - (CHAT_PADDING * 2) - totalHeight;
+
+        int currentY = y + this.getBaseYSize() - CHAT_PADDING - (int) (alignmentSpace * (1 - yMult));
+        for (int i = 0; i < linesToShow; i++) {
+            if (this.chatScroll + i >= this.chatMessageList.size()) continue;
+            final ChatLine line = this.chatMessageList.get(this.chatScroll + i);
+            if (line.updateCounter >= 190 && !ignoreFadeout) {
+                continue;
+            }
+            double fadeAmount = (double) line.updateCounter / 200D;
+            fadeAmount = 1.0D - fadeAmount;
+            fadeAmount *= 10D;
+            if (fadeAmount < 0.0D) {
+                fadeAmount = 0.0D;
+            }
+            if (fadeAmount > 1.0D) {
+                fadeAmount = 1.0D;
+            }
+            fadeAmount *= fadeAmount;
+            int alpha = (int) (255D * fadeAmount);
+            if (ignoreFadeout) {
+                alpha = 255;
+            }
+            if (alpha > 0) {
+                final CharSequence message = line.message;
+                final int h = MathHelper.ceil(mc.font.heightOfConstrainedChars(message, wrapWidth));
+                currentY -= (h + LINE_SPACING);
+                drawAlignedLine(hud, mc.font, message, x, currentY, h, alpha, wrapWidth);
+            }
+        }
+        GLRenderer.disableState(State.BLEND);
+    }
+
+    private void drawLines(Gui gui, FontRenderer sr, @NotNull List<String> messages, int x, int y, int alpha) {
+        GLRenderer.enableState(State.BLEND);
+        GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
+
+        int wrapWidth = getMessageWrapWidth();
+        int maxContentHeight = Math.max(1, this.getBaseYSize() - (CHAT_PADDING * 2));
+        List<String> visibleMessages = new ArrayList<>();
+        int totalHeight = 0;
+        for (String message : messages) {
+            int lineHeight = MathHelper.ceil(sr.heightOfConstrainedChars(message, wrapWidth)) + LINE_SPACING;
+            if (totalHeight + lineHeight > maxContentHeight) {
+                break;
+            }
+            visibleMessages.add(message);
+            totalHeight += lineHeight;
+        }
+
+        float yMult = GameSettings.VERTICAL_CHAT_TEXT_ALIGNMENT.value.multiplier;
+        int alignmentSpace = this.getBaseYSize() - (CHAT_PADDING * 2) - totalHeight;
+
+        int currentY = y + this.getBaseYSize() - CHAT_PADDING - (int) (alignmentSpace * (1 - yMult));
+        for (String message : visibleMessages) {
+            final int h = MathHelper.ceil(sr.heightOfConstrainedChars(message, wrapWidth));
+            currentY -= (h + LINE_SPACING);
+            drawAlignedLine(gui, sr, message, x, currentY, h, alpha, wrapWidth);
+        }
+
+        GLRenderer.disableState(State.BLEND);
+    }
+
+    private void drawAlignedLine(@NotNull Gui gui, @NotNull FontRenderer sr, CharSequence message, int x, int currentY, int h, int alpha, int wrapWidth) {
+        float xMult = GameSettings.HORIZONTAL_CHAT_TEXT_ALIGNMENT.value.multiplier;
+        int textWidth = Math.min(wrapWidth, (int) sr.stringWidthDouble(message));
+        int boxWidth = this.getBaseXSize() - (CHAT_PADDING * 2);
+        int renderX = x + CHAT_PADDING + (int) ((boxWidth - textWidth) * xMult);
+        int boxLeft = renderX - 1;
+        int boxRight = renderX + textWidth + 1;
+        gui.drawRect(boxLeft, currentY - 1, boxRight, currentY + h + 1, alpha / 2 << 24);
+        GLRenderer.enableState(State.BLEND);
+        sr.renderWidthConstrained(message, renderX, currentY, wrapWidth).setShadow().setColor(0xFFFFFF + (alpha << 24)).call();
+    }
+
+    private int computeTotalHeight(List<ChatLine> messages, int scroll, int linesUsed, boolean ignoreFadeout, int wrapWidth) {
+        int total = 0;
+        for (int i = 0; i < linesUsed; i++) {
+            int idx = scroll + i;
+            if (idx >= messages.size()) continue;
+            ChatLine line = messages.get(idx);
+            if (line.updateCounter >= 190 && !ignoreFadeout) continue;
+            total += MathHelper.ceil(mc.font.heightOfConstrainedChars(line.message, wrapWidth)) + LINE_SPACING;
+        }
+        return total;
+    }
+}
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentChatInput.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentChatInput.java
new file mode 100644
index 000000000..d3f78bb73
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentChatInput.java
@@ -0,0 +1,74 @@
+package net.minecraft.client.gui.hud.component;
+
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.hud.HudIngame;
+import net.minecraft.client.gui.hud.component.layout.Layout;
+import net.minecraft.client.gui.chat.ScreenChat;
+import net.minecraft.client.option.OptionGuiScaleOverride;
+import net.minecraft.client.render.renderer.BlendFactor;
+import net.minecraft.client.render.renderer.GLRenderer;
+import net.minecraft.client.render.renderer.State;
+import org.jetbrains.annotations.NotNull;
+
+public class HudComponentChatInput extends HudComponentMovable {
+    private HudComponentChat linkedChat;
+
+    public HudComponentChatInput(String key, int xSize, int ySize, Layout layout) {
+        super(key, xSize, ySize, layout);
+    }
+
+    public void linkChat(HudComponentChat chat) {
+        this.linkedChat = chat;
+    }
+
+    @Override
+    public int getBaseXSize() {
+        return this.linkedChat != null ? this.linkedChat.getBaseXSize() : super.getBaseXSize();
+    }
+
+    @Override
+    public OptionGuiScaleOverride getGuiScaleOverrideOption() {
+        return this.linkedChat != null ? this.linkedChat.getGuiScaleOverrideOption() : super.getGuiScaleOverrideOption();
+    }
+
+    @Override
+    public boolean isVisible() {
+        return mc.currentScreen instanceof ScreenChat;
+    }
+
+    @Override
+    public boolean isPreviewTranslucent() {
+        return isVisible();
+    }
+
+    @Override
+    public void render(HudIngame hud, int xSizeScreen, int ySizeScreen, float partialTick) {
+        // Nothing rendered natively by the HUD loop, because ScreenChat handles its own rendering.
+        // However, ScreenChat will use these Layout bounds to draw the text entry field.
+    }
+
+    @Override
+    public void renderPreview(@NotNull Gui gui, @NotNull Layout layout, int xSizeScreen, int ySizeScreen) {
+
+        renderTranslucency();
+
+        int x = layout.getComponentX(this, xSizeScreen);
+        int y = layout.getComponentY(this, ySizeScreen);
+
+        GLRenderer.enableState(State.BLEND);
+        GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
+        GLRenderer.pushFrame();
+        
+        int emotePickerButtonColor = 0x80ffffff;
+        int emotePickerTextColor = 0xffffffa0;
+        
+        gui.drawRect(x, y, x + 12, y + 12, emotePickerButtonColor);
+        gui.drawStringCenteredShadow(mc.font, Character.toString('☺'), x + 6, y + 2, emotePickerTextColor);
+
+        gui.drawRect(x + 14, y, x + getBaseXSize(), y + 12, 0x80000000);
+        gui.drawStringShadow(mc.font, "_", x + 16, y + 2, 0xE0E0E0);
+        
+        GLRenderer.popFrame();
+        GLRenderer.disableState(State.BLEND);
+    }
+}
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 25b6198b7..9c5fcec2e 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
@@ -17,6 +17,7 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.container.ContainerInventory;
 import net.minecraft.core.util.helper.LightIndexHelper;
+import org.jetbrains.annotations.NotNull;
 
 import static net.minecraft.client.Minecraft.HOTBAR_SWAP_ANIMATION_LENGTH_TICKS;
 
@@ -63,7 +64,7 @@ public class HudComponentHotbar extends HudComponentMovable {
 
     // Offset anchors to account for the selector dots depending on orientation
     @Override
-    public int getDisplayedAnchorX(ComponentAnchor anchor) {
+    public int getDisplayedAnchorX(@NotNull ComponentAnchor anchor) {
         int xAnchor = super.getDisplayedAnchorX(anchor);
         if (!this.isVertical()) {
             if (anchor.xPosition == 0.0f) {
@@ -76,7 +77,7 @@ public class HudComponentHotbar extends HudComponentMovable {
     }
 
     @Override
-    public int getDisplayedAnchorY(ComponentAnchor anchor) {
+    public int getDisplayedAnchorY(@NotNull ComponentAnchor anchor) {
         int yAnchor = super.getDisplayedAnchorY(anchor);
         if (this.isVertical()) {
             if (anchor.yPosition == 0.0f) {
@@ -175,7 +176,7 @@ public class HudComponentHotbar extends HudComponentMovable {
     }
 
     @Override
-    public void renderPreview(Gui gui, Layout layout, int xSizeScreen, int ySizeScreen) {
+    public void renderPreview(Gui gui, @NotNull Layout layout, int xSizeScreen, int ySizeScreen) {
         int x = layout.getComponentX(this, xSizeScreen);
         int y = layout.getComponentY(this, ySizeScreen);
         boolean isVertical = this.isVertical();
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 a9b59b7a7..65e7dc69a 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
@@ -17,6 +17,7 @@ import net.minecraft.core.world.season.Season;
 import net.minecraft.core.world.season.Seasons;
 import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.weather.Weathers;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -203,7 +204,7 @@ public class HudComponentInfoOverlay extends HudComponentMovable {
         drawLines(lines, x, y);
     }
 
-    private void drawLines(List<RenderLine> lines, int x, int y) {
+    private void drawLines(@NotNull List<RenderLine> lines, int x, int y) {
         if (lines.isEmpty()) return;
 
         int lineHeight = 10;
@@ -212,12 +213,12 @@ public class HudComponentInfoOverlay extends HudComponentMovable {
         float yMult = GameSettings.VERTICAL_INFO_TEXT_ALIGNMENT.value.multiplier;
 
         int padding = 2;
-        int startY = y + padding + (int) ((this.getDisplayedYSize() - (padding * 2) - totalHeight) * yMult);
+        int startY = y + padding + (int) ((this.getBaseYSize() - (padding * 2) - totalHeight) * yMult);
 
         for (int i = 0; i < lines.size(); i++) {
             RenderLine line = lines.get(i);
             int currentY = startY + (i * lineHeight);
-            drawAlignedString(line.text, x, currentY, this.getDisplayedXSize(), line.color);
+            drawAlignedString(line.text, x, currentY, this.getBaseXSize(), line.color);
         }
     }
 }
\ 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 455b1e9a7..ae1b12c06 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
@@ -5,8 +5,6 @@ import net.minecraft.client.console.LogMessageReceiver;
 import net.minecraft.client.gui.Gui;
 import net.minecraft.client.gui.hud.HudIngame;
 import net.minecraft.client.gui.hud.component.layout.Layout;
-import net.minecraft.client.gui.hud.component.layout.LayoutAbsolute;
-import net.minecraft.client.gui.hud.component.layout.LayoutSnap;
 import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.render.font.FontRenderer;
 import net.minecraft.client.render.renderer.BlendFactor;
@@ -14,7 +12,6 @@ import net.minecraft.client.render.renderer.GLRenderer;
 import net.minecraft.client.render.renderer.State;
 import net.minecraft.core.net.command.TextFormatting;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -74,6 +71,13 @@ public class HudComponentLog extends HudComponentMovable {
         return GameSettings.DEVELOPER_MODE.value;
     }
 
+    private void drawAlignedString(@NotNull FontRenderer sr, String text, int boxX, int boxY, int boxWidth, int argb) {
+        int textWidth = sr.stringWidth(text);
+        float xMult = GameSettings.HORIZONTAL_LOG_TEXT_ALIGNMENT.value.multiplier;
+        int renderX = boxX + PADDING + (int) ((boxWidth - (PADDING * 2) - textWidth) * xMult);
+        sr.render(text, renderX, boxY).setShadow().setColor(argb).call();
+    }
+
     @Override
     public void render(final @NotNull HudIngame hud, final int xSizeScreen, final int ySizeScreen, final float partialTick) {
         if (!this.callbackAdded) {
@@ -127,14 +131,7 @@ public class HudComponentLog extends HudComponentMovable {
             opacities[i] = this.logEntries.get(i).getOpacity();
         }
 
-        @Nullable ComponentAnchor anchor = null;
-        if (this.layout instanceof LayoutAbsolute layoutAbsolute) {
-            anchor = layoutAbsolute.getAnchor();
-        } else if (this.layout instanceof LayoutSnap layoutSnap) {
-            anchor = layoutSnap.getAnchor();
-        }
-
-        render(mc.font, x, y, messages, opacities, anchor);
+        render(mc.font, x, y, messages, opacities);
     }
 
     @Override
@@ -149,30 +146,22 @@ public class HudComponentLog extends HudComponentMovable {
             this.preludes.get(LogMessage.Level.ERROR) + "This is an error line!",
         };
 
-        @Nullable ComponentAnchor anchor = null;
-        if (layout instanceof LayoutAbsolute layoutAbsolute) {
-            anchor = layoutAbsolute.getAnchor();
-        } else if (layout instanceof LayoutSnap layoutSnap) {
-            anchor = layoutSnap.getAnchor();
-        }
-
-        render(mc.font, x, y, lines, new float[]{1.0f, 1.0f, 1.0f, 1.0f}, anchor);
+        render(mc.font, x, y, lines, new float[]{1.0f, 1.0f, 1.0f, 1.0f});
     }
 
-    private void render(final @NotNull FontRenderer sr, final int x, final int y, final @NotNull String @NotNull [] lines, final float @NotNull [] opacities, final @Nullable ComponentAnchor anchor) {
+    private void render(final @NotNull FontRenderer sr, final int x, final int y, final @NotNull String @NotNull [] lines, final float @NotNull [] opacities) {
         GLRenderer.enableState(State.BLEND);
         GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
-        for (int i = 0; i < lines.length; i++) {
-            @NotNull String line = lines[i];
 
-            final int lineWidth = sr.stringWidth(line);
-            if (anchor == null || anchor == ComponentAnchor.TOP_LEFT || anchor == ComponentAnchor.CENTER_LEFT || anchor == ComponentAnchor.BOTTOM_LEFT) {
-                sr.render(line, x + PADDING, y + PADDING + i * LINE_HEIGHT).setShadow().setColor(0x00_FF_FF_FF + ((int) (opacities[i] * 0xFF) << 24)).call();
-            } else if (anchor == ComponentAnchor.TOP_CENTER || anchor == ComponentAnchor.CENTER || anchor == ComponentAnchor.BOTTOM_CENTER) {
-                sr.render(line, x + PADDING + WIDTH / 2 - lineWidth / 2, y + PADDING + i * LINE_HEIGHT).setShadow().setColor(0x00_FF_FF_FF + ((int) (opacities[i] * 0xFF) << 24)).call();
-            } else {
-                sr.render(line, x + PADDING + WIDTH - lineWidth, y + PADDING + i * LINE_HEIGHT).setShadow().setColor(0x00_FF_FF_FF + ((int) (opacities[i] * 0xFF) << 24)).call();
-            }
+        float yMult = GameSettings.VERTICAL_LOG_TEXT_ALIGNMENT.value.multiplier;
+        int totalHeight = lines.length * LINE_HEIGHT;
+        int startY = y + PADDING + (int) ((this.getBaseYSize() - (PADDING * 2) - totalHeight) * yMult);
+
+        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);
         }
         GLRenderer.disableState(State.BLEND);
     }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentSubtitles.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentSubtitles.java
index 37d25ac4d..99f7b22e6 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentSubtitles.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentSubtitles.java
@@ -9,6 +9,7 @@ import net.minecraft.client.render.renderer.BlendFactor;
 import net.minecraft.client.render.renderer.GLRenderer;
 import net.minecraft.client.render.renderer.State;
 import net.minecraft.client.sound.SoundRepository;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -25,7 +26,13 @@ public class HudComponentSubtitles extends HudComponentMovable {
 
     @Override
     public boolean isEnabled() {
-        return GameSettings.SUBTITLES.value;
+        // Keep subtitles editable in HUD editor even when hidden in-game.
+        return true;
+    }
+
+    @Override
+    public boolean isPreviewTranslucent() {
+        return !isVisible();
     }
 
     @Override
@@ -35,6 +42,9 @@ public class HudComponentSubtitles extends HudComponentMovable {
 
     @Override
     public void renderPreview(Gui gui, Layout layout, int xSizeScreen, int ySizeScreen) {
+
+        renderTranslucency();
+
         List<SubtitleTracker.SubtitleEntry> example = new ArrayList<>();
         example.add(new SubtitleTracker.SubtitleEntry(SoundRepository.SOUNDS.getSoundEvent("mob.wolf.whine"), 0, 0, 0));
         example.add(new SubtitleTracker.SubtitleEntry(SoundRepository.SOUNDS.getSoundEvent("random.drr"), 0, 0, 0));
@@ -42,19 +52,22 @@ public class HudComponentSubtitles extends HudComponentMovable {
         drawChat(gui, example, xSizeScreen, ySizeScreen, 0);
     }
 
-    public void drawChat(Gui gui, List<SubtitleTracker.SubtitleEntry> subtitleEntries, int xSizeScreen, int ySizeScreen, float partialTick)
+    public void drawChat(Gui gui, @NotNull List<SubtitleTracker.SubtitleEntry> subtitleEntries, int xSizeScreen, int ySizeScreen, float partialTick)
     {
         int x = this.getLayout().getComponentX(this, xSizeScreen);
         int y = this.getLayout().getComponentY(this, ySizeScreen);
-        int width = getDisplayedXSize();
-        int height = getDisplayedYSize();
-        int xRight = x + width;
-        int yBottom = y + height;
+        int width = getBaseXSize();
+        int height = getBaseYSize();
         int messagesToShow = height/10;
         boolean ignoreFadeout = false;
+        int visibleEntries = Math.min(subtitleEntries.size(), messagesToShow);
+        int rowHeight = 9;
+        int blockHeight = visibleEntries * rowHeight;
+        float xMult = GameSettings.HORIZONTAL_SUBTITLE_TEXT_ALIGNMENT.value.multiplier;
+        float yMult = GameSettings.VERTICAL_SUBTITLE_TEXT_ALIGNMENT.value.multiplier;
 
         int maxMessageWidth = 0;
-        for (int i = 0; i < subtitleEntries.size() && i < messagesToShow; i++)
+        for (int i = 0; i < visibleEntries; i++)
         {
             SubtitleTracker.SubtitleEntry entry = subtitleEntries.get(i);
             if (entry.soundEvent == null) {
@@ -66,10 +79,14 @@ public class HudComponentSubtitles extends HudComponentMovable {
             }
         }
         maxMessageWidth += mc.font.stringWidth("<") + mc.font.stringWidth(">");
+        byte xPad = 3;
+        int boxWidth = maxMessageWidth + xPad * 2;
+        int blockLeft = x + Math.round(Math.max(0, width - boxWidth) * xMult);
+        int blockTop = y + Math.round(Math.max(0, height - blockHeight) * yMult);
 
         GLRenderer.enableState(State.BLEND);
         GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
-        for (int i = 0; i < subtitleEntries.size() && i < messagesToShow; i++)
+        for (int i = 0; i < visibleEntries; i++)
         {
             SubtitleTracker.SubtitleEntry entry = subtitleEntries.get(i);
             if (entry.soundEvent == null) {
@@ -89,25 +106,20 @@ public class HudComponentSubtitles extends HudComponentMovable {
             }
             fadeAmount *= fadeAmount;
             int alpha = (int) (255D * fadeAmount);
-            if (ignoreFadeout)
-            {
-                alpha = 255;
-            }
             if (alpha > 0)
             {
-                byte xPad = 3;
-                int y2 = -i * 9 - 8;
+                int renderY = blockTop + ((visibleEntries - 1 - i) * rowHeight);
                 final String subtitle = entry.soundEvent.getSubtitleTranslated();
                 if (subtitle != null) {
-                    gui.drawRect(xRight - maxMessageWidth - xPad * 2, yBottom + y2 - 1, xRight, yBottom + y2 + 8, alpha / 2 << 24);
+                    gui.drawRect(blockLeft, renderY - 1, blockLeft + boxWidth, renderY + 8, alpha / 2 << 24);
                     GLRenderer.enableState(State.BLEND);
-                    mc.font.renderCentered(subtitle, xRight - (maxMessageWidth) / 2 - xPad, yBottom + y2).setShadow().setColor(0xFFFFFF + (alpha << 24)).call();
+                    mc.font.renderCentered(subtitle, blockLeft + boxWidth / 2, renderY).setShadow().setColor(0xFFFFFF + (alpha << 24)).call();
                     if (mc.thePlayer != null) {
                         final double sin = Math.sin(entry.getRelativeAngle(mc.thePlayer) + Math.PI/2);
                         if (sin > 0.7) {
-                            mc.font.render("<", xRight - maxMessageWidth - xPad, yBottom + y2).setColor(0xFFFFFF + (alpha << 24)).call();
+                            mc.font.render("<", blockLeft + xPad / 2, renderY).setColor(0xFFFFFF + (alpha << 24)).call();
                         } else if (sin < -0.7) {
-                            mc.font.render(">", xRight - mc.font.stringWidth(">") - xPad/2, yBottom + y2).setColor(0xFFFFFF + (alpha << 24)).call();
+                            mc.font.render(">", blockLeft + boxWidth - mc.font.stringWidth(">") - xPad / 2, renderY).setColor(0xFFFFFF + (alpha << 24)).call();
                         }
                     }
                 }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponents.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponents.java
index 7e410dbd0..6ee04f34d 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponents.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponents.java
@@ -21,9 +21,11 @@ public class HudComponents {
     public static String DEFAULT_LAYOUT = null;
     public static final @Nullable HudComponents INSTANCE = new HudComponents();
 
-    // Absolute components
+    public static final @NotNull HudComponentChatInput CHAT_INPUT = register(
+        new HudComponentChatInput("chat_input", HudComponentChat.DEFAULT_CHAT_WIDTH, 14, new LayoutAbsolute(0.0f, 1.0f, ComponentAnchor.BOTTOM_LEFT, 0, 0))
+    );
     public static final @NotNull HudComponentHotbar HOTBAR = register(
-        new HudComponentHotbar("hotbar", new LayoutAbsolute(0.5f, 1.0f, ComponentAnchor.BOTTOM_CENTER, 0, -2))
+        new HudComponentHotbar("hotbar", new LayoutAbsolute(0.5f, 1.0f, ComponentAnchor.BOTTOM_CENTER, 0, 0))
             .addAttachedOption(GameSettings.VERTICAL_HOT_BAR, () -> new BooleanOptionComponent(GameSettings.VERTICAL_HOT_BAR))
     );
     public static final @NotNull HudComponentCrosshair CROSSHAIR = register(
@@ -31,13 +33,15 @@ public class HudComponents {
     );
     public static final @NotNull HudComponentSubtitles SUBTITLES = register(
         new HudComponentSubtitles("subtitles_box", 100, 50, new LayoutAbsolute(1.0f, 0.75f, ComponentAnchor.BOTTOM_RIGHT))
+            .addAttachedOption(GameSettings.SUBTITLES, () -> new BooleanOptionComponent(GameSettings.SUBTITLES))
+            .addAttachedOption(GameSettings.HORIZONTAL_SUBTITLE_TEXT_ALIGNMENT, () -> new ToggleableOptionComponent<>(GameSettings.HORIZONTAL_SUBTITLE_TEXT_ALIGNMENT))
+            .addAttachedOption(GameSettings.VERTICAL_SUBTITLE_TEXT_ALIGNMENT, () -> new ToggleableOptionComponent<>(GameSettings.VERTICAL_SUBTITLE_TEXT_ALIGNMENT))
     );
     public static final @NotNull HudComponentLog LOG = register(
         new HudComponentLog("log", new LayoutAbsolute(1.0f, 0.0f, ComponentAnchor.TOP_RIGHT))
+            .addAttachedOption(GameSettings.HORIZONTAL_LOG_TEXT_ALIGNMENT, () -> new ToggleableOptionComponent<>(GameSettings.HORIZONTAL_LOG_TEXT_ALIGNMENT))
+            .addAttachedOption(GameSettings.VERTICAL_LOG_TEXT_ALIGNMENT, () -> new ToggleableOptionComponent<>(GameSettings.VERTICAL_LOG_TEXT_ALIGNMENT))
     );
-
-    // public static final @NotNull HudComponentArmorDurability ARMOR_DURABILITY = register(new HudComponentArmorDurability("armor_durability", new LayoutAbsolute(0.0f, 1.0f, ComponentAnchor.BOTTOM_LEFT)));
-
     public static final @NotNull HudComponentInfoOverlay INFO_OVERLAY = register(
         new HudComponentInfoOverlay("info_overlay", new LayoutAbsolute(0.0f, 0.0f, ComponentAnchor.TOP_LEFT))
             .addAttachedOption(GameSettings.HORIZONTAL_INFO_TEXT_ALIGNMENT, () -> new ToggleableOptionComponent<>(GameSettings.HORIZONTAL_INFO_TEXT_ALIGNMENT))
@@ -54,6 +58,12 @@ public class HudComponents {
     );
 
     // Snapped components
+    public static final @NotNull HudComponentChat CHAT = register(
+        new HudComponentChat("chat", HudComponentChat.DEFAULT_CHAT_WIDTH, 110, new LayoutSnap(CHAT_INPUT, ComponentAnchor.TOP_LEFT, ComponentAnchor.BOTTOM_LEFT, 0, -50))
+            .addAttachedOption(GameSettings.chatVisibility, () -> new ToggleableOptionComponent<>(GameSettings.chatVisibility))
+            .addAttachedOption(GameSettings.HORIZONTAL_CHAT_TEXT_ALIGNMENT, () -> new ToggleableOptionComponent<>(GameSettings.HORIZONTAL_CHAT_TEXT_ALIGNMENT))
+            .addAttachedOption(GameSettings.VERTICAL_CHAT_TEXT_ALIGNMENT, () -> new ToggleableOptionComponent<>(GameSettings.VERTICAL_CHAT_TEXT_ALIGNMENT))
+    );
     public static final @NotNull HudComponentDynamicTooltip DYNAMIC_TOOLTIP = register(
         new HudComponentDynamicTooltip("dynamic_tooltip", new LayoutSnap(HOTBAR, ComponentAnchor.TOP_CENTER, ComponentAnchor.BOTTOM_CENTER, 0, -29))
             .addAttachedOption(GameSettings.HIDE_DYNAMIC_TOOLTIP, () -> new BooleanOptionComponent(GameSettings.HIDE_DYNAMIC_TOOLTIP))
@@ -121,6 +131,10 @@ public class HudComponents {
             .addAttachedOption(GameSettings.FLIP_HELD_ITEM_COUNT, () -> new BooleanOptionComponent(GameSettings.FLIP_HELD_ITEM_COUNT))
     );
 
+    static {
+        CHAT_INPUT.linkChat(CHAT);
+    }
+
     public static <T extends HudComponent> T register(T component) {
         if(INSTANCE == null) throw new IllegalStateException("HudComponents not initialized, Instance is null");
         INSTANCE.components.add(component);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/layout/LayoutAbsolute.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/layout/LayoutAbsolute.java
index b6da0e1e2..fe34da949 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/layout/LayoutAbsolute.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/layout/LayoutAbsolute.java
@@ -38,12 +38,14 @@ public class LayoutAbsolute extends Layout {
 
     @Override
     public int getComponentX(@NotNull HudComponent component, int xSizeScreen) {
-        return (int) (this.xPosition * xSizeScreen) - component.getTrueAnchorX(this.anchor) + this.xOffset;
+        int padding = (int) GameSettings.SCREEN_PADDING.value.floatValue();
+        return padding + (int) (this.xPosition * (xSizeScreen - padding * 2)) - component.getTrueAnchorX(this.anchor) + this.xOffset;
     }
 
     @Override
     public int getComponentY(@NotNull HudComponent component, int ySizeScreen) {
-        return (int) (this.yPosition * ySizeScreen) - component.getTrueAnchorY(this.anchor) + this.yOffset;
+        int padding = (int) GameSettings.SCREEN_PADDING.value.floatValue();
+        return padding + (int) (this.yPosition * (ySizeScreen - padding * 2)) - component.getTrueAnchorY(this.anchor) + this.yOffset;
     }
 
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/layout/LayoutSnap.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/layout/LayoutSnap.java
index d0cb4cb83..10e4e5d20 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/layout/LayoutSnap.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/layout/LayoutSnap.java
@@ -4,6 +4,7 @@ import net.minecraft.client.gui.ScreenHudEditor;
 import net.minecraft.client.gui.hud.component.ComponentAnchor;
 import net.minecraft.client.gui.hud.component.HudComponent;
 import net.minecraft.client.gui.hud.component.HudComponents;
+import net.minecraft.client.option.GameSettings;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -41,14 +42,15 @@ public class LayoutSnap extends Layout {
     @Override
     public int getComponentX(@NotNull HudComponent component, int xSizeScreen) {
         if (this.parent == null) {
-            return (int) (xSizeScreen * this.parentAnchor.xPosition) - component.getTrueAnchorX(this.anchor) + this.xOffset;
+            int padding = (int) GameSettings.SCREEN_PADDING.value.floatValue();
+            return padding + (int) ((xSizeScreen - padding * 2) * this.parentAnchor.xPosition) - component.getTrueAnchorX(this.anchor) + this.xOffset;
         }
 
         int posX = this.parent.getLayout().getComponentX(this.parent, xSizeScreen)
                 - component.getTrueAnchorX(this.anchor)
                 + this.parent.getTrueAnchorX(this.parentAnchor);
 
-        if (!this.parent.isVisible() && !(mc.currentScreen instanceof ScreenHudEditor)) {
+        if (component.isSnapToFill() && !this.parent.isVisible() && !(mc.currentScreen instanceof ScreenHudEditor)) {
             float collapseDirection = this.anchor.xPosition - this.parentAnchor.xPosition;
             posX += (int) (collapseDirection * this.parent.getTrueXSize());
         } else {
@@ -61,14 +63,15 @@ public class LayoutSnap extends Layout {
     @Override
     public int getComponentY(@NotNull HudComponent component, int ySizeScreen) {
         if (this.parent == null) {
-            return (int) (ySizeScreen * this.parentAnchor.yPosition) - component.getTrueAnchorY(this.anchor) + this.yOffset;
+            int padding = (int) GameSettings.SCREEN_PADDING.value.floatValue();
+            return padding + (int) ((ySizeScreen - padding * 2) * this.parentAnchor.yPosition) - component.getTrueAnchorY(this.anchor) + this.yOffset;
         }
 
         int posY = this.parent.getLayout().getComponentY(this.parent, ySizeScreen)
                 - component.getTrueAnchorY(this.anchor)
                 + this.parent.getTrueAnchorY(this.parentAnchor);
 
-        if (!this.parent.isVisible() && !(mc.currentScreen instanceof ScreenHudEditor)) {
+        if (component.isSnapToFill() && !this.parent.isVisible() && !(mc.currentScreen instanceof ScreenHudEditor)) {
             float collapseDirection = this.anchor.yPosition - this.parentAnchor.yPosition;
             posY += (int) (collapseDirection * this.parent.getTrueYSize());
         } else {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/BooleanToggleComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/BooleanToggleComponent.java
new file mode 100644
index 000000000..7070ed313
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/BooleanToggleComponent.java
@@ -0,0 +1,81 @@
+package net.minecraft.client.gui.options.components;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.SwitchElement;
+import net.minecraft.client.render.window.CursorShape;
+import net.minecraft.core.lang.I18n;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
+
+public class BooleanToggleComponent
+    extends ButtonComponent
+{
+    private final BooleanSupplier getter;
+    private final Consumer<Boolean> setter;
+    private final boolean defaultValue;
+    private final SwitchElement button;
+
+    public BooleanToggleComponent(String translationKey, boolean defaultValue, @NotNull BooleanSupplier getter, Consumer<Boolean> setter, @Nullable String tooltipTranslationKey) {
+        super(translationKey, tooltipTranslationKey);
+
+        this.getter = getter;
+        this.setter = setter;
+        this.defaultValue = defaultValue;
+        this.button = new SwitchElement(0, 0, 0, 150, 20, getter.getAsBoolean(), "", "");
+        updateButton();
+    }
+
+    public BooleanToggleComponent(String translationKey, boolean defaultValue, BooleanSupplier getter, Consumer<Boolean> setter) {
+        this(translationKey, defaultValue, getter, setter, null);
+    }
+
+    private void updateButton() {
+        this.button.setOn(this.getter.getAsBoolean());
+        I18n i18n = I18n.getInstance();
+        this.button.displayString = this.getter.getAsBoolean()
+            ? i18n.translateKey("options.on")
+            : i18n.translateKey("options.off");
+    }
+
+    @Override
+    public void resetValue() {
+        this.setter.accept(this.defaultValue);
+        updateButton();
+    }
+
+    @Override
+    public void init(Minecraft mc) {
+        updateButton();
+    }
+
+    @Override
+    public boolean isDefault() {
+        return this.getter.getAsBoolean() == this.defaultValue;
+    }
+
+    @Override
+    protected void buttonClicked(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
+        this.setter.accept(!this.getter.getAsBoolean());
+        updateButton();
+    }
+
+    @Override
+    protected void renderButton(int x, int y, int relativeButtonX, int relativeButtonY, int buttonWidth, int buttonHeight, int relativeMouseX, int relativeMouseY) {
+        super.renderButton(x, y, relativeButtonX, relativeButtonY, buttonWidth, buttonHeight, relativeMouseX, relativeMouseY);
+
+        this.button.xPosition = x + relativeButtonX;
+        this.button.yPosition = y + relativeButtonY;
+        this.button.width = buttonWidth;
+        this.button.height = buttonHeight;
+
+        this.button.drawButton(mc, x + relativeMouseX, y + relativeMouseY);
+
+        if (relativeMouseX >= relativeButtonX && relativeMouseX < relativeButtonX + buttonWidth && relativeMouseY >= relativeButtonY && relativeButtonY < relativeButtonY + buttonHeight) {
+            assert mc.currentScreen != null;
+            mc.currentScreen.setDesiredCursor(CursorShape.HAND);
+        }
+    }
+}
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/FloatSliderComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/FloatSliderComponent.java
new file mode 100644
index 000000000..4fba680e7
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/FloatSliderComponent.java
@@ -0,0 +1,101 @@
+package net.minecraft.client.gui.options.components;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.SliderElement;
+import net.minecraft.client.render.window.CursorShape;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class FloatSliderComponent
+    extends ButtonComponent
+{
+    private final Supplier<Float> getter;
+    private final Consumer<Float> setter;
+    private final float defaultValue;
+    private final float minValue;
+    private final float maxValue;
+    private final SliderElement slider;
+    private final Function<Float, String> formatter;
+
+    public FloatSliderComponent(String translationKey, float defaultValue, float minValue, float maxValue, Supplier<Float> getter, Consumer<Float> setter, Function<Float, String> formatter, @Nullable String tooltipTranslationKey) {
+        super(translationKey, tooltipTranslationKey);
+
+        this.getter = getter;
+        this.setter = setter;
+        this.defaultValue = defaultValue;
+        this.minValue = minValue;
+        this.maxValue = maxValue;
+        this.formatter = formatter;
+        this.slider = new SliderElement(0, 0, 0, 150, 20, formatter.apply(getter.get()), MathHelper.unlerp(minValue, maxValue, getter.get()));
+    }
+
+    public FloatSliderComponent(String translationKey, float defaultValue, float minValue, float maxValue, Supplier<Float> getter, Consumer<Float> setter, Function<Float, String> formatter) {
+        this(translationKey, defaultValue, minValue, maxValue, getter, setter, formatter, null);
+    }
+
+    @Override
+    protected void buttonClicked(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
+        this.slider.mouseClicked(mc, this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
+        applySliderValue();
+    }
+
+    @Override
+    protected void buttonDragged(int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
+        this.slider.mouseDragged(mc, this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
+        applySliderValue();
+    }
+
+    @Override
+    protected void buttonReleased(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
+        this.slider.mouseReleased(this.slider.xPosition + relativeMouseX, this.slider.yPosition + relativeMouseY);
+        applySliderValue();
+    }
+
+    private void applySliderValue() {
+        float value = (float) MathHelper.lerp(minValue, maxValue, this.slider.sliderValue);
+        this.setter.accept(value);
+        onChanged();
+    }
+
+    @Override
+    protected void renderButton(int x, int y, int relativeButtonX, int relativeButtonY, int buttonWidth, int buttonHeight, int relativeMouseX, int relativeMouseY) {
+        super.renderButton(x, y, relativeButtonX, relativeButtonY, buttonWidth, buttonHeight, relativeMouseX, relativeMouseY);
+
+        this.slider.xPosition = x + relativeButtonX;
+        this.slider.yPosition = y + relativeButtonY;
+        this.slider.width = buttonWidth;
+        this.slider.height = buttonHeight;
+
+        this.slider.drawButton(mc, x + relativeMouseX, y + relativeMouseY);
+
+        if (relativeMouseX >= relativeButtonX && relativeMouseX < relativeButtonX + buttonWidth && relativeMouseY >= relativeButtonY && relativeButtonY < relativeButtonY + buttonHeight) {
+            mc.currentScreen.setDesiredCursor(CursorShape.HAND);
+        }
+    }
+
+    @Override
+    public void resetValue() {
+        this.setter.accept(this.defaultValue);
+        this.slider.sliderValue = MathHelper.unlerp(minValue, maxValue, this.defaultValue);
+        onChanged();
+    }
+
+    @Override
+    public void init(Minecraft mc) {
+        this.slider.sliderValue = MathHelper.unlerp(minValue, maxValue, this.getter.get());
+        onChanged();
+    }
+
+    private void onChanged() {
+        this.slider.displayString = this.formatter.apply(this.getter.get());
+    }
+
+    @Override
+    public boolean isDefault() {
+        return Math.abs(this.getter.get() - this.defaultValue) < 0.0001f;
+    }
+}
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 c9d530942..5d5ba8232 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
@@ -60,7 +60,6 @@ public abstract class OptionsPages {
     public static OptionsPage LANGUAGE;
     public static OptionsPage SEARCH;
     public static OptionsPage DEBUG;
-    public static OptionsPage HIDDEN;
 
     public static OptionsPage register(OptionsPage page) {
         OptionsPageRegistry.getInstance().register(page);
@@ -83,6 +82,7 @@ public abstract class OptionsPages {
             .withComponent(new OptionsCategory("gui.options.page.general.category.user_interface")
                 .withComponent(new ShortcutComponent("gui.options.page.general.button.edit_hud", () -> mc.displayScreen(new ScreenHudEditor(mc.currentScreen))))
                 .withComponent(new ToggleableOptionComponent<>(GameSettings.GUI_SCALE).applyOnRelease())
+                .withComponent(new FloatOptionComponent(GameSettings.SCREEN_PADDING, 0, 100))
                 .withComponent(new TooltipPickerComponent(GameSettings.TOOLTIP_STYLE))
                 .withComponent(new ToggleableOptionComponent<>(GameSettings.FONT))
                 .withComponent(new ToggleableOptionComponent<>(GameSettings.chatVisibility))
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 d2dd33b26..42f2861ee 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
@@ -9,6 +9,7 @@ import net.minecraft.client.discord.RichPresenceHandlerThread;
 import net.minecraft.client.enums.MusicFrequency;
 import net.minecraft.client.enums.SelectedSoundtrack;
 import net.minecraft.client.gui.TooltipElement;
+import net.minecraft.client.gui.hud.component.HudComponent;
 import net.minecraft.client.gui.hud.component.HudComponents;
 import net.minecraft.client.gui.options.ScreenOptions;
 import net.minecraft.client.input.InputDevice;
@@ -134,7 +135,7 @@ public final class GameSettings {
     public static final @NotNull OptionBoolean TRANSPARENCY_DEPTH_CHECK = register(new OptionBoolean("transparencyDepthCheck", true));
     public static final @NotNull OptionEnum<ParticlesQuality> PARTICLES_QUALITY = register(new OptionEnum<>("particleQuality", ParticlesQuality.class, ParticlesQuality.ALL));
     public static final @NotNull OptionRange PARTICLES_CAP = register(new OptionRange("particleCap", 50000, 1000, 100000));
-    public static final @NotNull OptionRange PARTICLE_RENDER_DISTANCE = register(new OptionRange("particleRenderDistance", 12, 1, 24)
+    public static final @NotNull OptionRange PARTICLE_RENDER_DISTANCE = register(new OptionRange("particleRenderDistance", 8, 1, 24)
         .addOnChangeCallback((mc, option) -> {
             if (mc.currentScreen instanceof ScreenOptions) {
                 ScreenOptions.queueReload = true;
@@ -271,12 +272,22 @@ public final class GameSettings {
             }
         })
         .withDisplayStringProvider((mc, i18n, option) -> {
+            for (HudComponent component : HudComponents.INSTANCE.getComponents()) {
+                if (component.getScaleOverride() > 0) {
+                    return i18n.translateKey("options.guiScale.disabled");
+                }
+            }
             if (option.value == 0) {
                 return i18n.translateKey("options.guiScale.auto");
             } else {
                 return option.value + "x";
             }
         }));
+    public static final @NotNull OptionFloat SCREEN_PADDING = register(new OptionFloat("screenPadding", 2.0f)
+        .withDisplayStringProvider((mc, i18n, option) -> {
+            int pixels = (int) option.value.floatValue();
+            return pixels + "px";
+        }));
     public static final @NotNull OptionInteger OVERLAY_MODE = register(new OptionInteger("overlayMode", 0));
     public static final @NotNull OptionInteger ROTATION_OVERLAY_MODE = register(new OptionInteger("rotationOverlayMode", 0));
     public static final @NotNull OptionEnum<TextureAnimation> TEXTURE_ANIMATIONS = register(new OptionEnum<>("animations", TextureAnimation.class, TextureAnimation.CUSTOM)
@@ -292,6 +303,7 @@ public final class GameSettings {
             mc.renderGlobal.allChanged();
         }));
     public static final @NotNull OptionInteger PLAYER_LIST_POSITION = register(new OptionInteger("playerListPosition", 2));
+    public static final @NotNull OptionInteger LAST_CREATIVE_INVENTORY_PAGE = register(new OptionInteger("lastCreativeInventoryPage", 0));
     public static final @NotNull OptionFloat COLOR_CORRECTION = register(new OptionFloat("colorCorrection", 0.5f));
     public static final @NotNull OptionBoolean SNEAK_TOGGLE = register(new OptionBoolean("sneakToggle", false));
     public static final @NotNull OptionFloat AUTOSAVE_TIMER = register(new OptionFloat("autosaveTimer", 0.04166666666F)
@@ -320,7 +332,7 @@ public final class GameSettings {
             return option.toOptionsString();
         }));
     public static final @NotNull OptionEnum<RenderScale> RENDER_SCALE = register(new OptionEnum<>("renderScale", RenderScale.class, RenderScale.SCALE_100));
-    public static final @NotNull OptionFloat HEAT_HAZE = register(new OptionFloat("heatHaze", 0));
+    public static final @NotNull OptionFloat HEAT_HAZE = register(new OptionFloat("heatHaze", 50));
     public static final @NotNull OptionBoolean ALPHA_MENU = register(new OptionBoolean("old", false));
     public static final @NotNull OptionBoolean ENABLE_ITEM_CLUMPING = register(new OptionBoolean("enableItemClumping", true));
     public static final @NotNull OptionEnum<DescriptionPromptEnum> ITEM_DESCRIPTIONS = register(new OptionEnum<>("itemDescriptions", DescriptionPromptEnum.class, DescriptionPromptEnum.PROMPT));
@@ -479,19 +491,19 @@ public final class GameSettings {
     public static final @NotNull OptionBoolean HIDE_HELD_ITEM_COUNT = register(new OptionBoolean("hideHeldItemCount", true));
 
     public static final @NotNull OptionEnum<ArmorHiddenState> HIDE_HELMET_BAR = register(
-        new OptionEnum<>("hideHelmetBar", ArmorHiddenState.class, ArmorHiddenState.NEVER)
+        new OptionEnum<>("hideHelmetBar", ArmorHiddenState.class, ArmorHiddenState.WHEN_NOT_WEARING)
             .setIsSlider(true)
     );
     public static final @NotNull OptionEnum<ArmorHiddenState> HIDE_CHESTPLATE_BAR = register(
-        new OptionEnum<>("hideChestplateBar", ArmorHiddenState.class, ArmorHiddenState.NEVER)
+        new OptionEnum<>("hideChestplateBar", ArmorHiddenState.class, ArmorHiddenState.WHEN_NOT_WEARING)
             .setIsSlider(true)
     );
     public static final @NotNull OptionEnum<ArmorHiddenState> HIDE_LEGGINGS_BAR = register(
-        new OptionEnum<>("hideLeggingsBar", ArmorHiddenState.class, ArmorHiddenState.NEVER)
+        new OptionEnum<>("hideLeggingsBar", ArmorHiddenState.class, ArmorHiddenState.WHEN_NOT_WEARING)
             .setIsSlider(true)
     );
     public static final @NotNull OptionEnum<ArmorHiddenState> HIDE_BOOTS_BAR = register(
-        new OptionEnum<>("hideBootsBar", ArmorHiddenState.class, ArmorHiddenState.NEVER)
+        new OptionEnum<>("hideBootsBar", ArmorHiddenState.class, ArmorHiddenState.WHEN_NOT_WEARING)
             .setIsSlider(true)
     );
 
@@ -519,7 +531,15 @@ public final class GameSettings {
             .setIsSlider(true)
     );
     public static final @NotNull OptionEnum<HorizontalTextAlignment> HORIZONTAL_LOG_TEXT_ALIGNMENT = register(
-        new OptionEnum<>("horizontalLogTextAlignment", HorizontalTextAlignment.class, HorizontalTextAlignment.LEFT)
+        new OptionEnum<>("horizontalLogTextAlignment", HorizontalTextAlignment.class, HorizontalTextAlignment.RIGHT)
+            .setIsSlider(true)
+    );
+    public static final @NotNull OptionEnum<HorizontalTextAlignment> HORIZONTAL_CHAT_TEXT_ALIGNMENT = register(
+        new OptionEnum<>("horizontalChatTextAlignment", HorizontalTextAlignment.class, HorizontalTextAlignment.LEFT)
+            .setIsSlider(true)
+    );
+    public static final @NotNull OptionEnum<HorizontalTextAlignment> HORIZONTAL_SUBTITLE_TEXT_ALIGNMENT = register(
+        new OptionEnum<>("horizontalSubtitleTextAlignment", HorizontalTextAlignment.class, HorizontalTextAlignment.RIGHT)
             .setIsSlider(true)
     );
     public static final @NotNull OptionEnum<VerticalTextAlignment> VERTICAL_INFO_TEXT_ALIGNMENT = register(
@@ -530,6 +550,14 @@ public final class GameSettings {
         new OptionEnum<>("verticalLogTextAlignment", VerticalTextAlignment.class, VerticalTextAlignment.TOP)
             .setIsSlider(true)
     );
+    public static final @NotNull OptionEnum<VerticalTextAlignment> VERTICAL_CHAT_TEXT_ALIGNMENT = register(
+        new OptionEnum<>("verticalChatTextAlignment", VerticalTextAlignment.class, VerticalTextAlignment.BOTTOM)
+            .setIsSlider(true)
+    );
+    public static final @NotNull OptionEnum<VerticalTextAlignment> VERTICAL_SUBTITLE_TEXT_ALIGNMENT = register(
+        new OptionEnum<>("verticalSubtitleTextAlignment", VerticalTextAlignment.class, VerticalTextAlignment.BOTTOM)
+            .setIsSlider(true)
+    );
 
     //KeyBind Options
     public static final @NotNull KeyBinding KEY_ATTACK = register(new KeyBinding("key.attack").setDefault(InputDevice.mouse, 0));
diff --git a/game/client/src/main/java/net/minecraft/client/option/OptionGuiScaleOverride.java b/game/client/src/main/java/net/minecraft/client/option/OptionGuiScaleOverride.java
new file mode 100644
index 000000000..d75a8cb59
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/option/OptionGuiScaleOverride.java
@@ -0,0 +1,83 @@
+package net.minecraft.client.option;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.ScaledResolution;
+import net.minecraft.core.lang.I18n;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Per-instance scale override for HUD components. Behaves much like
+ * {@link OptionGuiScale}, but with a "Disabled" entry instead of "Auto"; when
+ * {@code value == 0} the component should fall back to the global GUI scale.
+ *
+ * <p>Instances of this class are intentionally NOT registered through
+ * {@link GameSettings#register}: each HUD Component
+ * owns its own instance and serializes it as part of its own settings string.
+ */
+public class OptionGuiScaleOverride extends OptionToggleable<Integer> {
+    public OptionGuiScaleOverride() {
+        super("guiScaleOverride", 0, new Integer[1]);
+    }
+
+    @Override
+    public void toggle() {
+        toggle(1);
+    }
+
+    @Override
+    public void toggle(int delta) {
+        int size = size();
+        setValueWithIndex((getValueIndex() + delta) % size);
+    }
+
+    @Override
+    public int getValueIndex() {
+        int max = size();
+        if (this.value <= 0 || this.value >= max) {
+            return 0;
+        }
+        return max - this.value;
+    }
+
+    @Override
+    public void setValueWithIndex(int i) {
+        if (i != 0) {
+            this.value = size() - i;
+        } else {
+            this.value = 0;
+        }
+    }
+
+    @Override
+    public int size() {
+        Minecraft mc = Minecraft.getMinecraft();
+        int width = mc.gameWindow.getWidthScreenCoords();
+        int height = mc.gameWindow.getHeightScreenCoords();
+        return ScaledResolution.getMaxScale(width, height);
+    }
+
+    @Override
+    public boolean isSlider() {
+        return true;
+    }
+
+    @Override
+    public void fromOptionsString(@NotNull String string) {
+        try {
+            this.value = Integer.parseInt(string);
+        } catch (NumberFormatException e) {
+            this.value = 0;
+        }
+    }
+
+    @Override
+    public @NotNull String getDisplayString() {
+        if (this.displayStringProvider != null) {
+            return this.displayStringProvider.getDisplayString(Minecraft.getMinecraft(), I18n.getInstance(), this);
+        }
+        if (this.value <= 0) {
+            return I18n.getInstance().translateKey("options.guiScaleOverride.disabled");
+        }
+        return this.value + "x";
+    }
+}
diff --git a/game/client/src/main/java/net/minecraft/client/render/ClientFireOverlayHelper.java b/game/client/src/main/java/net/minecraft/client/render/ClientFireOverlayHelper.java
index ee6f726ce..4a0d2a754 100644
--- a/game/client/src/main/java/net/minecraft/client/render/ClientFireOverlayHelper.java
+++ b/game/client/src/main/java/net/minecraft/client/render/ClientFireOverlayHelper.java
@@ -22,4 +22,11 @@ public final class ClientFireOverlayHelper {
 
         return "minecraft:block/fire";
     }
+    public static boolean usesSulfuricFireOverlay(final @Nullable Entity entity) {
+        if (entity == null || entity.activeFireBlock == null) {
+            return false;
+        }
+        return entity.activeFireBlock == Blocks.FIRE_SULFURIC
+            || entity.activeFireBlock.hasTag(BlockTags.SULFURIC_FIRE_OVERLAY_SOURCE);
+    }
 }
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java b/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java
index c77be5e92..ba93e9343 100644
--- a/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java
@@ -21,8 +21,8 @@ import net.minecraft.core.block.Block;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.util.helper.LightIndexHelper;
 import net.minecraft.core.util.helper.MathHelper;
+import net.minecraft.core.util.helper.LightIndexHelper;
 import net.minecraft.core.world.pos.TilePos;
 import org.joml.Math;
 
@@ -251,7 +251,11 @@ public class ItemRenderer {
 
         texture.parentAtlas.bind();
 
-        GLRenderer.setColor4f(1.0F, 1.0F, 1.0F, 0.85F);
+        if (ClientFireOverlayHelper.usesSulfuricFireOverlay(this.mc.thePlayer)) {
+            GLRenderer.setColor4f(1.0F, 0.70F, 0.24F, 0.85F);
+        } else {
+            GLRenderer.setColor4f(1.0F, 1.0F, 1.0F, 0.85F);
+        }
         GLRenderer.enableState(State.BLEND);
         GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/Lighting.java b/game/client/src/main/java/net/minecraft/client/render/Lighting.java
index aa4f2e796..9a8f53aa2 100644
--- a/game/client/src/main/java/net/minecraft/client/render/Lighting.java
+++ b/game/client/src/main/java/net/minecraft/client/render/Lighting.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.render;
 
-import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.renderer.GLRenderer;
 import org.jetbrains.annotations.NotNull;
 import org.joml.Math;
@@ -16,10 +15,12 @@ public final class Lighting {
         GLRenderer.globalGetLight0().enabled = false;
         GLRenderer.globalGetLight1().enabled = false;
 //        glDisable(GL_COLOR_MATERIAL);
+        GLRenderer.setLightMapStrength(0f);
     }
 
     public static void enableInventoryLight() {
         enableLight(0.4f, 0.5f);
+        GLRenderer.setLightMapStrength(0f);
         GLRenderer.globalGetNormalTransformMatrix()
             .rotateY(Math.toRadians(-30.0f))
             .rotateX(Math.toRadians(155.0f))
@@ -36,6 +37,7 @@ public final class Lighting {
         GLRenderer.globalGetLight0().enabled = true;
         GLRenderer.globalGetLight1().enabled = true;
 //        glEnable(GL_COLOR_MATERIAL);
+        GLRenderer.setLightMapStrength(1f);
 //        glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
 
         GLRenderer.globalGetLight0().position.set(0.2f, 1.0f, -0.7f).normalize();
diff --git a/game/client/src/main/java/net/minecraft/client/render/LightmapHelper.java b/game/client/src/main/java/net/minecraft/client/render/LightmapHelper.java
index ced5da4e6..3854739bc 100644
--- a/game/client/src/main/java/net/minecraft/client/render/LightmapHelper.java
+++ b/game/client/src/main/java/net/minecraft/client/render/LightmapHelper.java
@@ -10,6 +10,7 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.ScreenPhotoMode;
 import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.option.enums.LightmapStyle;
+import net.minecraft.client.render.renderer.GLRenderer;
 import net.minecraft.client.util.helper.Textures;
 import net.minecraft.client.util.helper.Buffer;
 import net.minecraft.client.world.WorldClient;
diff --git a/game/client/src/main/java/net/minecraft/client/render/ParticleEngine.java b/game/client/src/main/java/net/minecraft/client/render/ParticleEngine.java
index 79a2c9bfa..0daeb80e6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/ParticleEngine.java
+++ b/game/client/src/main/java/net/minecraft/client/render/ParticleEngine.java
@@ -18,8 +18,9 @@ import net.minecraft.client.render.tessellator.TessellatorParticle;
 import net.minecraft.client.render.tessellator.TessellatorParticleShader;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.BlockLogicFire;
 import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.material.MaterialGas;
+import net.minecraft.core.block.material.MaterialLiquid;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
@@ -262,7 +263,8 @@ public final class ParticleEngine {
     public void destroy(@NotNull TilePosc blockPos, int id, int data) {
         if (GameSettings.PARTICLES_QUALITY.value == ParticlesQuality.NONE) return;
         Block<?> block = Blocks.blocksList[id];
-        if (block == null || block.getLogic() instanceof BlockLogicFire) return;
+        final var material = block.getMaterial();
+        if (material instanceof MaterialGas || material instanceof MaterialLiquid) return;
         int amount = GameSettings.PARTICLES_QUALITY.value == ParticlesQuality.REDUCED ? 2 : 4;
 
         AABBdc bounds = block.getLogic().getBoundsFromState(this.world, blockPos);
diff --git a/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java b/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
index 66736be6b..fd5b5ea7f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/WorldRenderer.java
@@ -663,6 +663,7 @@ public class WorldRenderer {
         TextureRegistry.worldAtlas.bind();
 
         Debug.change("terrain");
+        Lighting.enableLight();
         GLRenderer.pushFrame();
         GLRenderer.setDepthFunc(CompareFunc.LESS_EQUAL);
         GL41.glActiveTexture(GL41.GL_TEXTURE2);
@@ -670,7 +671,6 @@ public class WorldRenderer {
         GL41.glActiveTexture(GL41.GL_TEXTURE3);
         TextureRegistry.worldAtlas.layerTextureMap.get("maskColor").bind();
         GL41.glActiveTexture(GL41.GL_TEXTURE0);
-        Lighting.enableLight();
         GLRenderer.setShader(Shaders.TERRAIN);
         GLRenderer.globalSetUniforms(Shaders.TERRAIN);
         this.lightmapHelper.enableLightmapRendering();
@@ -686,9 +686,12 @@ public class WorldRenderer {
         particleEngine.renderLitParticles(this.mc.activeCamera, partialTicks);
         Lighting.disable();
         this.fogManager.setupFog(FogManager.FOG_MODE_NORMAL, this.farPlaneDistance, partialTicks, GLRenderer.getFogState());
+        GLRenderer.pushFrame();
+        GLRenderer.setLightMapStrength(1f);
         this.mc.renderer.beginRenderParticles(partialTicks);
         particleEngine.renderParticles(this.mc.activeCamera, partialTicks);
         this.mc.renderer.endRenderParticles(partialTicks);
+        GLRenderer.popFrame();
 
         this.lightmapHelper.disableLightmapRendering();
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
index 5fe4cd627..fb11ab398 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
@@ -383,7 +383,7 @@ public final class BlockModelDispatcher
         addDispatch(new BlockModelGenericButton<>(Blocks.BUTTON_GLOOMSTONE, "minecraft:block/button/stone/gloomstone"));
         addDispatch(new BlockModelGenericButton<>(Blocks.BUTTON_SANDSTONE, "minecraft:block/button/stone/sandstone"));
         addDispatch(new BlockModelGenericButton<>(Blocks.BUTTON_BRIMSTONE, "minecraft:block/button/stone/brimstone"));
-        addDispatch(new BlockModelGenericButton<>(Blocks.BUTTON_PLANKS, "minecraft:block/button/planks/oak"));
+        addDispatch(new BlockModelGenericButton<>(Blocks.BUTTON_PLANKS_OAK, "minecraft:block/button/planks/oak"));
         addDispatch(new BlockModelGenericButtonPainted<>(Blocks.BUTTON_PLANKS_PAINTED));
 
         addDispatch(new BlockModelGenericLever<>(Blocks.LEVER_COBBLE_STONE).render3D(false));
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/generic/BlockModelGenericMatcher.java b/game/client/src/main/java/net/minecraft/client/render/block/model/generic/BlockModelGenericMatcher.java
index f5eb59693..cd0474632 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/generic/BlockModelGenericMatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/generic/BlockModelGenericMatcher.java
@@ -1,16 +1,21 @@
 package net.minecraft.client.render.block.model.generic;
 
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
+import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.block.BlockLogicAxisAligned;
+import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.pos.TilePosc;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.useless.dragonfly.models.block.StaticBlockModel;
 
 import java.util.Random;
 
-public class BlockModelGenericMatcher<T extends BlockLogic> extends BlockModelGenericAxis<T> {
+public class BlockModelGenericMatcher<T extends BlockLogic> extends BlockModelGeneric<T> {
     public final @NotNull StaticBlockModel[] models = new StaticBlockModel[4];
     public final Random random = new Random();
     public BlockModelGenericMatcher(@NotNull Block<T> block, @NotNull String baseKey) {
@@ -20,6 +25,23 @@ public class BlockModelGenericMatcher<T extends BlockLogic> extends BlockModelGe
         }
     }
 
+    @Override
+    public boolean renderAttached(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos, boolean cullFaces, @Nullable IconCoordinate overrideTexture) {
+        Axis axis = BlockLogicAxisAligned.metaToAxis(worldSource.getBlockData(tilePos));
+        switch (axis) {
+            case X -> {
+                return getModel(worldSource, tilePos).renderAttached(this, tessellator, worldSource, tilePos, 0, 1, 3, 0, 0, 0, false, cullFaces, overrideTexture);
+            }
+            case Y -> {
+                return getModel(worldSource, tilePos).renderAttached(this, tessellator, worldSource, tilePos, 0, 0, 0, 0, 0, 0, false, cullFaces, overrideTexture);
+            }
+            case Z -> {
+                return getModel(worldSource, tilePos).renderAttached(this, tessellator, worldSource, tilePos, 1, 0, 0, 0, 0, 0, false, cullFaces, overrideTexture);
+            }
+        }
+        return false;
+    }
+
     @Override
     public @NotNull StaticBlockModel getModel(@NotNull WorldSource source, @NotNull TilePosc tilePosc) {
         this.random.setSeed(getPositionalSeed(tilePosc));
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/generic/BlockModelGenericSlab.java b/game/client/src/main/java/net/minecraft/client/render/block/model/generic/BlockModelGenericSlab.java
index 39393183f..5d1bcca76 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/generic/BlockModelGenericSlab.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/generic/BlockModelGenericSlab.java
@@ -2,7 +2,13 @@ package net.minecraft.client.render.block.model.generic;
 
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
+import net.minecraft.core.util.helper.Direction;
+import net.minecraft.core.world.WorldSource;
+import net.minecraft.core.world.pos.TilePos;
+import net.minecraft.core.world.pos.TilePosc;
+import net.minecraft.core.world.type.WorldType;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.useless.dragonfly.data.block.BlockModelData;
 import org.useless.dragonfly.models.block.StaticBlockModel;
 
@@ -23,4 +29,34 @@ public class BlockModelGenericSlab<T extends BlockLogic> extends BlockModelGener
             default -> this.staticModel;
         };
     }
+
+    private final @NotNull TilePos queryPos = new TilePos();
+    @Override
+    public boolean cullSide(@NotNull WorldSource worldSource, @NotNull TilePosc blockPos, @Nullable Direction direction) {
+        int data = worldSource.getBlockData(blockPos);
+        boolean upperFaceVisible = (data & 0b11) == 1 || (data & 0b11) == 2;
+        boolean lowerFaceVisible = (data & 0b11) == 0 || (data & 0b11) == 1;
+
+        if (direction != null) {
+            // Cull world ceiling and floors
+            WorldType worldType = worldSource.getWorldType();
+            if (worldType.hasCeiling() && direction == Direction.UP && blockPos.y() >= worldType.getMaxY(worldSource) && upperFaceVisible) {
+                return true;
+            } else if (direction == Direction.DOWN && blockPos.y() <= worldType.getMinY(worldSource) && lowerFaceVisible) {
+                return true;
+            }
+
+            TilePos shifted = blockPos.add(direction, this.queryPos);
+            Block<?> b = worldSource.getBlockType(shifted);
+            if (b == this.block) {
+                int otherData = worldSource.getBlockData(shifted);
+                if (otherData == 1) return true;
+                int selfData = worldSource.getBlockData(blockPos);
+                return selfData == otherData;
+            } else {
+                return worldSource.isBlockOpaqueCube(shifted);
+            }
+        }
+        return false;
+    }
 }
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 c0060d244..67cf599d0 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
@@ -93,7 +93,14 @@ public class FontRendererDefault extends FontRenderer {
                     if (formatCode != -1) {
                         switch (cNext) {
                             case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': {
-                                this.currentConfig = SF.setColor(this.currentConfig, Colors.allChatColors[MathHelper.clamp(formatCode, 0, 15)].value);
+                                // Preserve the base alpha (e.g. chat fadeout) when
+                                // applying legacy text formatting colors.
+                                int rgb = Colors.allChatColors[MathHelper.clamp(formatCode, 0, 15)].value & 0x00_FF_FF_FF;
+                                int alpha = SF.getColor(baseConfig) & 0xFF_00_00_00;
+                                if (alpha == 0) {
+                                    alpha = 0xFF_00_00_00;
+                                }
+                                this.currentConfig = SF.setColor(this.currentConfig, rgb | alpha);
                                 break;
                             }
                             case 'k': {
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModel.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModel.java
index 2e6d097dc..11aca3cf6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModel.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModel.java
@@ -104,5 +104,5 @@ public abstract class ItemModel {
         GLRenderer.popFrame();
     }
 
-    public abstract IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack);
+    public abstract IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack);
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBlock.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBlock.java
index 1410f7417..ef0b3afca 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBlock.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBlock.java
@@ -31,7 +31,7 @@ public class ItemModelBlock extends ItemModelStandard {
     }
 
     @Override
-    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack) {
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack) {
         IconCoordinate overlay = this.blockModel.getOverlayTexture(itemStack.getMetadata());
         return overlay != null ? overlay : BlockModelStandard.BLOCK_TEXTURE_UNASSIGNED;
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java
index 91db639ab..c9d62eed1 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java
@@ -14,8 +14,8 @@ import org.jetbrains.annotations.Nullable;
 import org.joml.Math;
 
 public class ItemModelBow extends ItemModelStandard {
-    public ItemModelBow(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelBow(@NotNull Item item, boolean defaultTextureLookup) {
+        super(item, defaultTextureLookup);
     }
 
     @Override
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucket.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucket.java
index a0a6d2f40..6bd95d81a 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucket.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucket.java
@@ -18,11 +18,11 @@ public abstract class ItemModelBucket extends ItemModelStandard {
 
     protected final Map<NamespaceID, IconCoordinate[]> bucketIcons = new HashMap<>();
 
-    public ItemModelBucket(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelBucket(@NotNull Item item, boolean defaultTextureLookup) {
+        super(item, defaultTextureLookup);
     }
 
-    protected void initializeIcons(String namespace, String prefix, int maxCharges, Set<NamespaceID> validStates) {
+    protected void initializeIcons(@NotNull String namespace, @NotNull String prefix, int maxCharges, @NotNull Set<@NotNull NamespaceID> validStates) {
         IconCoordinate[] emptyArray = new IconCoordinate[1];
         emptyArray[0] = TextureRegistry.getTexture(namespace + ":item/" + prefix + "/empty");
         this.bucketIcons.put(ItemBucket.STATE_EMPTY, emptyArray);
@@ -42,7 +42,7 @@ public abstract class ItemModelBucket extends ItemModelStandard {
     }
 
     @Override
-    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack) {
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack) {
         NamespaceID state = ItemBucket.getState(itemStack);
         int charges = ItemBucket.getCharges(itemStack);
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucketIron.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucketIron.java
index fc70c6e39..f7ee8c842 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucketIron.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucketIron.java
@@ -3,12 +3,13 @@ package net.minecraft.client.render.item.model;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemBucket;
 import net.minecraft.core.util.collection.NamespaceID;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Set;
 
 public class ItemModelBucketIron extends ItemModelBucket {
-    public ItemModelBucketIron(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelBucketIron(@NotNull Item item, String namespace) {
+        super(item, false);
         Set<NamespaceID> validStates = ItemBucket.getRegisteredStateIds();
         this.initializeIcons(namespace, "bucket_iron", 1, validStates);
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucketSteel.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucketSteel.java
index 13600c632..af71b6555 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucketSteel.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBucketSteel.java
@@ -3,12 +3,13 @@ package net.minecraft.client.render.item.model;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemBucket;
 import net.minecraft.core.util.collection.NamespaceID;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Set;
 
 public class ItemModelBucketSteel extends ItemModelBucket {
-    public ItemModelBucketSteel(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelBucketSteel(@NotNull Item item, String namespace) {
+        super(item, false);
         Set<NamespaceID> validStates = ItemBucket.getRegisteredStateIds();
         this.initializeIcons(namespace, "bucket_steel", 3, validStates);
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelCoal.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelCoal.java
index 2867671ad..2ba9ca2f6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelCoal.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelCoal.java
@@ -10,12 +10,12 @@ import org.jetbrains.annotations.Nullable;
 
 public class ItemModelCoal extends ItemModelStandard {
     protected IconCoordinate charcoal = TextureRegistry.getTexture("minecraft:item/charcoal");
-    public ItemModelCoal(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelCoal(@NotNull Item item, boolean defaultTextureLookup) {
+        super(item, defaultTextureLookup);
     }
 
     @Override
-    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack)
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack)
     {
         if(itemStack.getMetadata() == 1)
             return charcoal;
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDispatcher.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDispatcher.java
index 20241c95e..87b3af8b0 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDispatcher.java
@@ -49,365 +49,365 @@ public class ItemModelDispatcher extends Dispatcher<Item, ItemModel> {
 
     public void reload() {
         dispatches.clear();
-        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_IRON, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_IRON)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_IRON, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_IRON)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_AXE_IRON, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_AXE_IRON)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_FIRESTRIKER_IRON, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.TOOL_FIRESTRIKER_IRON));
 
-        addDispatch(new ItemModelStandard(Items.FOOD_APPLE, "minecraft"));
-        addDispatch(new ItemModelBow(Items.TOOL_BOW, "minecraft")
+        addDispatch(new ItemModelStandard(Items.FOOD_APPLE));
+        addDispatch(new ItemModelBow(Items.TOOL_BOW, true)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, new DisplayPos(1.13f/16f, 3.2f/16f, 1.13f/16f, 0, -90, 25, 0.68f, 0.68f, 0.68f))
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, new DisplayPos(1.13f/16f, 3.2f/16f, 1.13f/16f, 0, 90, -25, 0.68f, 0.68f, 0.68f))
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, new DisplayPos(-1f/16f, -2f/16f, 2.5f/16f, -80, 260, -40, 0.9f, 0.9f, 0.9f))
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, new DisplayPos(-1f/16f, -2f/16f, 2.5f/16f, -80, -280, 40, 0.9f, 0.9f, 0.9f)));
-        addDispatch(new ItemModelStandard(Items.AMMO_ARROW, "minecraft"));
-        addDispatch(new ItemModelCoal(Items.COAL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.DIAMOND, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.INGOT_IRON, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.INGOT_GOLD, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.AMMO_ARROW));
+        addDispatch(new ItemModelCoal(Items.COAL, true));
+        addDispatch(new ItemModelStandard(Items.DIAMOND));
+        addDispatch(new ItemModelStandard(Items.INGOT_IRON));
+        addDispatch(new ItemModelStandard(Items.INGOT_GOLD));
 
-        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_IRON, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_IRON)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_WOOD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_WOOD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_WOOD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_WOOD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_WOOD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_WOOD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_AXE_WOOD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_AXE_WOOD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_STONE, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_STONE)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_STONE, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_STONE)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_STONE, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_STONE)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_AXE_STONE, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_AXE_STONE)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_DIAMOND, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_DIAMOND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_DIAMOND, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_DIAMOND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_DIAMOND, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_DIAMOND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_AXE_DIAMOND, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_AXE_DIAMOND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
 
-        addDispatch(new ItemModelStandard(Items.STICK, "minecraft")
+        addDispatch(new ItemModelStandard(Items.STICK)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.BOWL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_STEW_MUSHROOM, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.BOWL));
+        addDispatch(new ItemModelStandard(Items.FOOD_STEW_MUSHROOM));
 
-        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_GOLD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_GOLD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_GOLD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_GOLD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_GOLD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_GOLD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_AXE_GOLD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_AXE_GOLD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
 
-        addDispatch(new ItemModelStandard(Items.STRING, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FEATHER_CHICKEN, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.GUNPOWDER, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.STRING));
+        addDispatch(new ItemModelStandard(Items.FEATHER_CHICKEN));
+        addDispatch(new ItemModelStandard(Items.GUNPOWDER));
 
-        addDispatch(new ItemModelStandard(Items.TOOL_HOE_WOOD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_HOE_WOOD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_HOE_STONE, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_HOE_STONE)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_HOE_IRON, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_HOE_IRON)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_HOE_DIAMOND, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_HOE_DIAMOND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_HOE_GOLD, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_HOE_GOLD)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
 
-        addDispatch(new ItemModelStandard(Items.SEEDS_WHEAT, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.WHEAT, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_BREAD, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.SEEDS_WHEAT));
+        addDispatch(new ItemModelStandard(Items.WHEAT));
+        addDispatch(new ItemModelStandard(Items.FOOD_BREAD));
 
-        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_LEATHER, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_LEATHER, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_LEATHER, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_LEATHER, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_LEATHER));
+        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_LEATHER));
+        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_LEATHER));
+        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_LEATHER));
 
-        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_CHAINMAIL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_CHAINMAIL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_CHAINMAIL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_CHAINMAIL, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_CHAINMAIL));
+        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_CHAINMAIL));
+        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_CHAINMAIL));
+        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_CHAINMAIL));
 
-        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_IRON, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_IRON, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_IRON, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_IRON, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_IRON));
+        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_IRON));
+        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_IRON));
+        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_IRON));
 
-        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_DIAMOND, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_DIAMOND, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_DIAMOND, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_DIAMOND, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_DIAMOND));
+        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_DIAMOND));
+        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_DIAMOND));
+        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_DIAMOND));
 
-        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_GOLD, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_GOLD, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_GOLD, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_GOLD, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_GOLD));
+        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_GOLD));
+        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_GOLD));
+        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_GOLD));
 
-        addDispatch(new ItemModelStandard(Items.FLINT, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_PORKCHOP_RAW, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_PORKCHOP_COOKED, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.PAINTING, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_APPLE_GOLD, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.SIGN, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.DOOR_OAK, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.DOOR_GLASS, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.FLINT));
+        addDispatch(new ItemModelStandard(Items.FOOD_PORKCHOP_RAW));
+        addDispatch(new ItemModelStandard(Items.FOOD_PORKCHOP_COOKED));
+        addDispatch(new ItemModelStandard(Items.PAINTING));
+        addDispatch(new ItemModelStandard(Items.FOOD_APPLE_GOLD));
+        addDispatch(new ItemModelStandard(Items.SIGN));
+        addDispatch(new ItemModelStandard(Items.DOOR_OAK));
+        addDispatch(new ItemModelStandard(Items.DOOR_GLASS));
         addDispatch(new ItemModelDoorPainted(Items.DOOR_OAK_PAINTED));
         addDispatch(new ItemModelBucketIron(Items.BUCKET_IRON, "minecraft"));
         addDispatch(new ItemModelBucketSteel(Items.BUCKET_STEEL, "minecraft"));
-      //addDispatch(new ItemModelStandard(Items.BUCKET_WATER, "minecraft"));
-      //addDispatch(new ItemModelStandard(Items.BUCKET_LAVA, "minecraft").setFullBright());
-        addDispatch(new ItemModelStandard(Items.MINECART, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.SADDLE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.DOOR_IRON, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.DUST_REDSTONE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.AMMO_SNOWBALL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.BOAT, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.LEATHER, "minecraft"));
-      //addDispatch(new ItemModelStandard(Items.BUCKET_MILK, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.BRICK_CLAY, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.CLAY, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.SUGARCANE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.PAPER, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.BOOK, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.SLIMEBALL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.MINECART_CHEST, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.MINECART_FURNACE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.EGG_CHICKEN, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.TOOL_COMPASS, "minecraft"));
-        addDispatch(new ItemModelFishingRod(Items.TOOL_FISHINGROD, "minecraft")
+      //addDispatch(new ItemModelStandard(Items.BUCKET_WATER));
+      //addDispatch(new ItemModelStandard(Items.BUCKET_LAVA).setFullBright());
+        addDispatch(new ItemModelStandard(Items.MINECART));
+        addDispatch(new ItemModelStandard(Items.SADDLE));
+        addDispatch(new ItemModelStandard(Items.DOOR_IRON));
+        addDispatch(new ItemModelStandard(Items.DUST_REDSTONE));
+        addDispatch(new ItemModelStandard(Items.AMMO_SNOWBALL));
+        addDispatch(new ItemModelStandard(Items.BOAT));
+        addDispatch(new ItemModelStandard(Items.LEATHER));
+      //addDispatch(new ItemModelStandard(Items.BUCKET_MILK));
+        addDispatch(new ItemModelStandard(Items.BRICK_CLAY));
+        addDispatch(new ItemModelStandard(Items.CLAY));
+        addDispatch(new ItemModelStandard(Items.SUGARCANE));
+        addDispatch(new ItemModelStandard(Items.PAPER));
+        addDispatch(new ItemModelStandard(Items.BOOK));
+        addDispatch(new ItemModelStandard(Items.SLIMEBALL));
+        addDispatch(new ItemModelStandard(Items.MINECART_CHEST));
+        addDispatch(new ItemModelStandard(Items.MINECART_FURNACE));
+        addDispatch(new ItemModelStandard(Items.EGG_CHICKEN));
+        addDispatch(new ItemModelStandard(Items.TOOL_COMPASS));
+        addDispatch(new ItemModelFishingRod(Items.TOOL_FISHINGROD, true)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_ROD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_ROD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_ROD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_ROD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_CLOCK, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.TOOL_CLOCK));
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.GLOWSTONE.asItem()).setFullBright());
-        addDispatch(new ItemModelStandard(Items.DUST_GLOWSTONE, "minecraft").setFullBright());
-        addDispatch(new ItemModelStandard(Items.FOOD_FISH_RAW, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_FISH_COOKED, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.DUST_GLOWSTONE).setFullBright());
+        addDispatch(new ItemModelStandard(Items.FOOD_FISH_RAW));
+        addDispatch(new ItemModelStandard(Items.FOOD_FISH_COOKED));
         addDispatch(new ItemModelDye(Items.DYE));
-        addDispatch(new ItemModelStandard(Items.BONE, "minecraft")
+        addDispatch(new ItemModelStandard(Items.BONE)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.DUST_SUGAR, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_CAKE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_PUMPKIN_PIE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.BED, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.REPEATER, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_COOKIE, "minecraft"));
-        addDispatch(new ItemModelMap(Items.MAP, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.TOOL_SHEARS, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.DUST_SUGAR));
+        addDispatch(new ItemModelStandard(Items.FOOD_CAKE));
+        addDispatch(new ItemModelStandard(Items.FOOD_PUMPKIN_PIE));
+        addDispatch(new ItemModelStandard(Items.BED));
+        addDispatch(new ItemModelStandard(Items.REPEATER));
+        addDispatch(new ItemModelStandard(Items.FOOD_COOKIE));
+        addDispatch(new ItemModelMap(Items.MAP, true));
+        addDispatch(new ItemModelStandard(Items.TOOL_SHEARS));
 
-        addDispatch(new ItemModelStandard(Items.TIMER, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.TIMER));
 
-        addDispatch(new ItemModelStandard(Items.NETHERCOAL, "minecraft").setFullBright());
+        addDispatch(new ItemModelStandard(Items.NETHERCOAL).setFullBright());
 
-        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_STEEL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_STEEL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_STEEL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_STEEL, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.ARMOR_HELMET_STEEL));
+        addDispatch(new ItemModelStandard(Items.ARMOR_CHESTPLATE_STEEL));
+        addDispatch(new ItemModelStandard(Items.ARMOR_LEGGINGS_STEEL));
+        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_STEEL));
 
-        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_STEEL, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SWORD_STEEL)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_STEEL, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_SHOVEL_STEEL)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_STEEL, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_PICKAXE_STEEL)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_AXE_STEEL, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_AXE_STEEL)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.TOOL_HOE_STEEL, "minecraft")
+        addDispatch(new ItemModelStandard(Items.TOOL_HOE_STEEL)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
 
-        addDispatch(new ItemModelStandard(Items.INGOT_STEEL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.INGOT_STEEL_CRUDE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.AMMO_FIREBALL, "minecraft").setFullBright());
-        addDispatch(new ItemModelStandard(Items.ARMOR_QUIVER_GOLD, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.HANDCANNON_UNLOADED, "minecraft")
+        addDispatch(new ItemModelStandard(Items.INGOT_STEEL));
+        addDispatch(new ItemModelStandard(Items.INGOT_STEEL_CRUDE));
+        addDispatch(new ItemModelStandard(Items.AMMO_FIREBALL).setFullBright());
+        addDispatch(new ItemModelStandard(Items.ARMOR_QUIVER_GOLD));
+        addDispatch(new ItemModelStandard(Items.HANDCANNON_UNLOADED)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.CHAINLINK, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.CLOTH, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.AMMO_CHARGE_EXPLOSIVE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.HANDCANNON_LOADED, "minecraft")
+        addDispatch(new ItemModelStandard(Items.CHAINLINK));
+        addDispatch(new ItemModelStandard(Items.CLOTH));
+        addDispatch(new ItemModelStandard(Items.AMMO_CHARGE_EXPLOSIVE));
+        addDispatch(new ItemModelStandard(Items.HANDCANNON_LOADED)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND).setFullBright());
-        addDispatch(new ItemModelStandard(Items.AMMO_ARROW_GOLD, "minecraft"));
-        addDispatch(new ItemModelQuiver(Items.ARMOR_QUIVER, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.TOOL_CALENDAR, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ORE_RAW_GOLD, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ORE_RAW_IRON, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.QUARTZ, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.OLIVINE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.AMMO_PEBBLE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_CHERRY, "minecraft"));
-      //addDispatch(new ItemModelStandard(Items.BUCKET_ICECREAM, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.AMMO_ARROW_PURPLE, "minecraft"));
-        addDispatch(new ItemModelLabel(Items.LABEL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.JAR, "minecraft"));
-
-        addDispatch(new ItemModelStandard(Items.LANTERN_FIREFLY_GREEN, "minecraft").setFullBright());
-        addDispatch(new ItemModelStandard(Items.LANTERN_FIREFLY_BLUE, "minecraft").setFullBright());
-        addDispatch(new ItemModelStandard(Items.LANTERN_FIREFLY_ORANGE, "minecraft").setFullBright());
-        addDispatch(new ItemModelStandard(Items.LANTERN_FIREFLY_RED, "minecraft").setFullBright());
+        addDispatch(new ItemModelStandard(Items.AMMO_ARROW_GOLD));
+        addDispatch(new ItemModelQuiver(Items.ARMOR_QUIVER, true));
+        addDispatch(new ItemModelStandard(Items.TOOL_CALENDAR));
+        addDispatch(new ItemModelStandard(Items.ORE_RAW_GOLD));
+        addDispatch(new ItemModelStandard(Items.ORE_RAW_IRON));
+        addDispatch(new ItemModelStandard(Items.QUARTZ));
+        addDispatch(new ItemModelStandard(Items.OLIVINE));
+        addDispatch(new ItemModelStandard(Items.AMMO_PEBBLE));
+        addDispatch(new ItemModelStandard(Items.FOOD_CHERRY));
+      //addDispatch(new ItemModelStandard(Items.BUCKET_ICECREAM));
+        addDispatch(new ItemModelStandard(Items.AMMO_ARROW_PURPLE));
+        addDispatch(new ItemModelLabel(Items.LABEL, true));
+        addDispatch(new ItemModelStandard(Items.JAR));
+
+        addDispatch(new ItemModelStandard(Items.LANTERN_FIREFLY_GREEN).setFullBright());
+        addDispatch(new ItemModelStandard(Items.LANTERN_FIREFLY_BLUE).setFullBright());
+        addDispatch(new ItemModelStandard(Items.LANTERN_FIREFLY_ORANGE).setFullBright());
+        addDispatch(new ItemModelStandard(Items.LANTERN_FIREFLY_RED).setFullBright());
 
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.LAMP_ACTIVE.asItem()).setFullBright());
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.LAMP_IDLE.asItem()).setFullBright());
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.LAMP_INVERTED_ACTIVE.asItem()).setFullBright());
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.LAMP_INVERTED_IDLE.asItem()).setFullBright());
 
-        addDispatch(new ItemModelStandard(Items.BASKET, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FLAG, "minecraft")
+        addDispatch(new ItemModelStandard(Items.BASKET));
+        addDispatch(new ItemModelStandard(Items.FLAG)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
 
-        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_ICESKATES, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.TOOL_SHEARS_STEEL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.TOOL_FIRESTRIKER_STEEL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.SEEDS_PUMPKIN, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.SEAT, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.ARMOR_BOOTS_ICESKATES));
+        addDispatch(new ItemModelStandard(Items.TOOL_SHEARS_STEEL));
+        addDispatch(new ItemModelStandard(Items.TOOL_FIRESTRIKER_STEEL));
+        addDispatch(new ItemModelStandard(Items.SEEDS_PUMPKIN));
+        addDispatch(new ItemModelStandard(Items.SEAT));
 
-        addDispatch(new ItemModelStandard(Items.ROPE, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.ROPE));
 
-        addDispatch(new ItemModelStandard(Items.WAND_MONSTER_SPAWNER, "minecraft")
+        addDispatch(new ItemModelStandard(Items.WAND_MONSTER_SPAWNER)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.WAND_NBT, "minecraft")
+        addDispatch(new ItemModelStandard(Items.WAND_NBT)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, HANDHELD_FIRST_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, HANDHELD_FIRST_PERSON_LEFT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, HANDHELD_THIRD_PERSON_RIGHT_HAND)
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, HANDHELD_THIRD_PERSON_LEFT_HAND));
-        addDispatch(new ItemModelStandard(Items.DOOR_STEEL, "minecraft"));
-        addDispatch(new ItemModelPaintbrush(Items.PAINTBRUSH, "minecraft")
+        addDispatch(new ItemModelStandard(Items.DOOR_STEEL));
+        addDispatch(new ItemModelPaintbrush(Items.PAINTBRUSH, true)
             .setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND,  new DisplayPos(1.13f/16f, 3.2f/16f, 1.13f/16f, 90, -90, 25, 0.68f, 0.68f, 0.68f))
             .setDisplayPos(DisplayPos.FIRST_PERSON_LEFT_HAND, new DisplayPos(1.13f/16f, 3.2f/16f, 1.13f/16f, 90, 90, -25, 0.68f, 0.68f, 0.68f))
             .setDisplayPos(DisplayPos.THIRD_PERSON_RIGHT_HAND, new DisplayPos(0, 4.0f/16f, 0.5f/16f, 90, -90, 55, 0.85f, 0.85f, 0.85f))
             .setDisplayPos(DisplayPos.THIRD_PERSON_LEFT_HAND, new DisplayPos(0, 4.0f/16f, 0.5f/16f, 90,  90, -55, 0.85f, 0.85f, 0.85f)));
 
-        addDispatch(new ItemModelStandard(Items.RECORD_13, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_CAT, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_BLOCKS, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_CHIRP, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_FAR, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_MALL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_MELLOHI, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_STAL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_STRAD, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_WARD, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_WAIT, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.RECORD_DOG, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.RECORD_13));
+        addDispatch(new ItemModelStandard(Items.RECORD_CAT));
+        addDispatch(new ItemModelStandard(Items.RECORD_BLOCKS));
+        addDispatch(new ItemModelStandard(Items.RECORD_CHIRP));
+        addDispatch(new ItemModelStandard(Items.RECORD_FAR));
+        addDispatch(new ItemModelStandard(Items.RECORD_MALL));
+        addDispatch(new ItemModelStandard(Items.RECORD_MELLOHI));
+        addDispatch(new ItemModelStandard(Items.RECORD_STAL));
+        addDispatch(new ItemModelStandard(Items.RECORD_STRAD));
+        addDispatch(new ItemModelStandard(Items.RECORD_WARD));
+        addDispatch(new ItemModelStandard(Items.RECORD_WAIT));
+        addDispatch(new ItemModelStandard(Items.RECORD_DOG));
 
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.TORCH_COAL.asItem()).setFullBright());
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.TORCH_REDSTONE_ACTIVE.asItem()).setFullBright());
@@ -417,24 +417,24 @@ public class ItemModelDispatcher extends Dispatcher<Item, ItemModel> {
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.PORTAL_DRIFT.asItem()).setFullBright());
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.PORTAL_NETHER.asItem()).setFullBright());
 
-        addDispatch(new ItemModelStandard(Items.JAR_BUTTERFLY_BLUE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.JAR_BUTTERFLY_ORANGE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.JAR_BUTTERFLY_PINK, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.JAR_BUTTERFLY_SILVER, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.JAR_BUTTERFLY_BLUE));
+        addDispatch(new ItemModelStandard(Items.JAR_BUTTERFLY_ORANGE));
+        addDispatch(new ItemModelStandard(Items.JAR_BUTTERFLY_PINK));
+        addDispatch(new ItemModelStandard(Items.JAR_BUTTERFLY_SILVER));
 
-        addDispatch(new ItemModelStandard(Items.STATUE_STONE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.STATUE_BASALT, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.STATUE_LIMESTONE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.STATUE_GRANITE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.STATUE_MARBLE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.STATUE_PIGMAN, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.STATUE_STONE));
+        addDispatch(new ItemModelStandard(Items.STATUE_BASALT));
+        addDispatch(new ItemModelStandard(Items.STATUE_LIMESTONE));
+        addDispatch(new ItemModelStandard(Items.STATUE_GRANITE));
+        addDispatch(new ItemModelStandard(Items.STATUE_MARBLE));
+        addDispatch(new ItemModelStandard(Items.STATUE_PIGMAN));
 
         addDispatch(new ItemModelSignPainted(Items.SIGN_PAINTED));
 
-        addDispatch(new ItemModelStandard(Items.FOOD_VENISON_RAW, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.FOOD_VENISON_COOKED, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.FOOD_VENISON_RAW));
+        addDispatch(new ItemModelStandard(Items.FOOD_VENISON_COOKED));
 
-        addDispatch(new ItemModelStandard(Items.RUBYGLASS, "minecraft").setFullBright());
+        addDispatch(new ItemModelStandard(Items.RUBYGLASS).setFullBright());
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.RUBYGLASS_COLUMN.asItem()).setFullBright());
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.BLOCK_RUBYGLASS.asItem()).setFullBright());
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.RUBYGLASS_GROWTH.asItem()).setFullBright());
@@ -443,23 +443,23 @@ public class ItemModelDispatcher extends Dispatcher<Item, ItemModel> {
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.BOULDER_MAGMATIC.asItem()));
         addDispatch(new ItemModelBlock((ItemBlock<?>) Blocks.BOULDER_SULFURIC.asItem()));
 
-        addDispatch(new ItemModelStandard(Items.DOUGH, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.DOUGH));
 
-        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_LEATHER, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_CHAINMAIL, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_IRON, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_DIAMOND, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_GOLD, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_STEEL, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_LEATHER));
+        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_CHAINMAIL));
+        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_IRON));
+        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_DIAMOND));
+        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_GOLD));
+        addDispatch(new ItemModelStandard(Items.ARMOR_WOLF_STEEL));
 
-        addDispatch(new ItemModelStandard(Items.AMMO_ARROW_FLAMING, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.AMMO_ARROW_FLAMING));
 
-        addDispatch(new ItemModelStandard(Items.SULFUR, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.SULFUR));
 
-        addDispatch(new ItemModelStandard(Items.STATUE_GLOOMSTONE, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.STATUE_NETHERRACK, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.STATUE_PERMAFROST, "minecraft"));
-        addDispatch(new ItemModelStandard(Items.STATUE_SLATE, "minecraft"));
+        addDispatch(new ItemModelStandard(Items.STATUE_GLOOMSTONE));
+        addDispatch(new ItemModelStandard(Items.STATUE_NETHERRACK));
+        addDispatch(new ItemModelStandard(Items.STATUE_PERMAFROST));
+        addDispatch(new ItemModelStandard(Items.STATUE_SLATE));
 
         for (int i = 0; i < Blocks.blocksList.length; i++) {
             if (Blocks.blocksList[i] == null) continue;
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDoorPainted.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDoorPainted.java
index a40772c34..724eed3cc 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDoorPainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDoorPainted.java
@@ -18,7 +18,7 @@ public class ItemModelDoorPainted extends ItemModelStandard {
     public ItemModelDoorPainted(Item item) {
         super(item, null);
     }
-    public @NotNull IconCoordinate getIcon(Entity entity, ItemStack itemStack){
+    public @NotNull IconCoordinate getIcon(Entity entity, @NotNull ItemStack itemStack){
         int meta = itemStack.getMetadata();
         return doorIcons[meta & DyeColor.MASK_COLOR];
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDye.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDye.java
index 575a2c636..d1e0a4854 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDye.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelDye.java
@@ -20,7 +20,7 @@ public class ItemModelDye extends ItemModelStandard {
         super(item, null);
     }
 
-    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack){
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack){
         int meta = itemStack.getMetadata();
         return dyeIcons[meta & DyeColor.MASK_COLOR];
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelFishingRod.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelFishingRod.java
index 40441a96e..053d68151 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelFishingRod.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelFishingRod.java
@@ -11,12 +11,12 @@ import org.jetbrains.annotations.Nullable;
 
 public class ItemModelFishingRod extends ItemModelStandard {
     protected IconCoordinate rodCast = TextureRegistry.getTexture("minecraft:item/tool_fishingrod_cast");
-    public ItemModelFishingRod(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelFishingRod(@NotNull Item item, boolean defaultTextureLookup) {
+        super(item, defaultTextureLookup);
     }
 
     @Override
-    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack){
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack){
         if (entity instanceof Player){
             // Use the cast fishing rod texture when holding a cast rod
             if(itemStack == ((Player) entity).getHeldItem() && ((Player) entity).bobberEntity != null)
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelLabel.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelLabel.java
index 28b2fdb10..404bda4cf 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelLabel.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelLabel.java
@@ -10,12 +10,12 @@ import org.jetbrains.annotations.Nullable;
 
 public class ItemModelLabel extends ItemModelStandard {
     protected IconCoordinate writtenLabel = TextureRegistry.getTexture("minecraft:item/label_written");
-    public ItemModelLabel(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelLabel(@NotNull Item item, boolean defaultTextureLookup) {
+        super(item, defaultTextureLookup);
     }
 
     @Override
-    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack)
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack)
     {
         if(itemStack.hasCustomName()) {
             return writtenLabel;
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelMap.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelMap.java
index 88dc401bf..b69ecdb1f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelMap.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelMap.java
@@ -27,8 +27,8 @@ public class ItemModelMap extends ItemModelStandard {
     private final Minecraft mc = Minecraft.getMinecraft();
     private final MapItemRenderer renderMapInstance = new MapItemRenderer();
 
-    public ItemModelMap(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelMap(Item item, boolean defaultTextureLookup) {
+        super(item, defaultTextureLookup);
     }
 
     @Override
@@ -123,7 +123,7 @@ public class ItemModelMap extends ItemModelStandard {
     }
 
     @Override
-    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack) {
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack) {
         if (!ItemMap.hasInitialized(itemStack)) {
             return TextureRegistry.getTexture("minecraft:item/map_blank");
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelNone.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelNone.java
index f68209e11..34280eb21 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelNone.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelNone.java
@@ -26,7 +26,7 @@ public class ItemModelNone extends ItemModel{
     }
 
     @Override
-    public IconCoordinate getIcon(@Nullable final Entity entity, final ItemStack itemStack) {
+    public IconCoordinate getIcon(@Nullable final Entity entity, final @NotNull ItemStack itemStack) {
         return null;
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelPaintbrush.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelPaintbrush.java
index accefcc40..802f9b16c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelPaintbrush.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelPaintbrush.java
@@ -19,12 +19,12 @@ public class ItemModelPaintbrush extends ItemModelStandard {
         }
     }
 
-    public ItemModelPaintbrush(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelPaintbrush(@NotNull Item item, boolean defaultTextureLookup) {
+        super(item, defaultTextureLookup);
     }
 
     @Override
-    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack) {
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack) {
         final DyeColor color = ItemPaintBrush.getColor(itemStack);
         if (color == null) {
             return emptyIcon;
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelQuiver.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelQuiver.java
index fcc90a9e6..585c8a2fa 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelQuiver.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelQuiver.java
@@ -10,12 +10,12 @@ import org.jetbrains.annotations.Nullable;
 
 public class ItemModelQuiver extends ItemModelStandard {
     protected IconCoordinate quiverFull = TextureRegistry.getTexture("minecraft:item/armor_quiver_empty");
-    public ItemModelQuiver(Item item, String namespace) {
-        super(item, namespace);
+    public ItemModelQuiver(@NotNull Item item, boolean defaultTextureLookup) {
+        super(item, defaultTextureLookup);
     }
 
     @Override
-    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack)
+    public @NotNull IconCoordinate getIcon(@Nullable Entity entity, @NotNull ItemStack itemStack)
     {
         if(itemStack.getMetadata() >= itemStack.getItem().getMaxDamage())
             return quiverFull;
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelSignPainted.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelSignPainted.java
index c7eb9ee08..f8556aa1c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelSignPainted.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelSignPainted.java
@@ -18,7 +18,7 @@ public class ItemModelSignPainted extends ItemModelStandard {
     public ItemModelSignPainted(Item item) {
         super(item, null);
     }
-    public @NotNull IconCoordinate getIcon(Entity entity, ItemStack itemStack){
+    public @NotNull IconCoordinate getIcon(Entity entity, @NotNull ItemStack itemStack){
         int meta = itemStack.getMetadata();
         return sign[meta & DyeColor.MASK_COLOR];
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java
index 7789cc5ab..8ed16bce8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java
@@ -13,6 +13,7 @@ import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.LightIndexHelper;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -42,7 +43,20 @@ public class ItemModelStandard extends ItemModel{
 
     protected boolean itemfullBright = false;
 
-    public ItemModelStandard(final Item item, final String namespace) {
+    public ItemModelStandard(final @NotNull Item item) {
+        this(item, true);
+    }
+
+    // Legacy constructor
+    @Deprecated
+    public ItemModelStandard(final @NotNull Item item, final @Nullable String namespace) {
+        this(item, false);
+        if (namespace != null){
+            this.icon = TextureRegistry.getTexture(namespace + ":item/" + item.getKey().substring("item.".length()).replace(".", "_"));
+        }
+    }
+
+    public ItemModelStandard(final @NotNull Item item, final boolean defaultTextureLookup) {
         super(item);
         this.displayPosMap.put(DisplayPos.GROUND, DEFAULT_ITEM_GROUND);
         this.displayPosMap.put(DisplayPos.HEAD, DEFAULT_ITEM_HEAD);
@@ -51,8 +65,8 @@ public class ItemModelStandard extends ItemModel{
         this.displayPosMap.put(DisplayPos.FIRST_PERSON_RIGHT_HAND, DEFAULT_ITEM_FIRST_PERSON_RIGHT_HAND);
         this.displayPosMap.put(DisplayPos.FIRST_PERSON_LEFT_HAND, DEFAULT_ITEM_FIRST_PERSON_LEFT_HAND); // TODO make automatic since its just the axis flipped
         this.displayPosMap.put(DisplayPos.FIXED, DEFAULT_ITEM_FIXED);
-        if (namespace != null){
-            this.icon = TextureRegistry.getTexture(namespace + ":item/" + item.getKey().substring("item.".length()).replace(".", "_"));
+        if (defaultTextureLookup){
+            this.icon = TextureRegistry.getTexture(item.namespaceID);
         }
     }
 
@@ -250,7 +264,7 @@ public class ItemModelStandard extends ItemModel{
         tessellator.addVertex(x + width,y,          z);
     }
 
-    public @NotNull IconCoordinate getIcon(@Nullable final Entity entity, final ItemStack itemStack){
+    public @NotNull IconCoordinate getIcon(@Nullable final Entity entity, final @NotNull ItemStack itemStack){
         return this.icon;
     }
     public int getColor(final ItemStack stack)
@@ -262,9 +276,19 @@ public class ItemModelStandard extends ItemModel{
         return 0xffffffff;
     }
 
-    public ItemModelStandard setFullBright()
+    public @NotNull ItemModelStandard setFullBright()
     {
         this.itemfullBright = true;
         return this;
     }
+
+    public @NotNull ItemModelStandard setIcon(@NotNull NamespaceID textureId) {
+        this.icon = TextureRegistry.getTexture(textureId);
+        return this;
+    }
+
+    public @NotNull ItemModelStandard setIcon(@NotNull String textureId) {
+        this.icon = TextureRegistry.getTexture(textureId);
+        return this;
+    }
 }
\ No newline at end of file
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 0cbf0a55f..a71958762 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
@@ -128,6 +128,9 @@ public class GLRenderer {
     private final float[] alphaTestStack = new float[RENDER_FRAMES_STACK_SIZE];
     private float currentAlphaTest = 0.1f;
 
+    private final float[] lightMapStrengthStack = new float[RENDER_FRAMES_STACK_SIZE];
+    private float currentLightMapStrength = 1f;
+
     private int stackIndex = 0;
 
 
@@ -158,6 +161,7 @@ public class GLRenderer {
         shader.uniformMat4f("model", modelM4f());
         shader.uniformMat4f("texture", textureM4f());
 
+        shader.uniformFloat("uLightMapStrength", instance.currentLightMapStrength);
         shader.uniformFloat("uAlphaTest", instance.currentAlphaTest);
         shader.uniformVec4f("uColor", Color.redFromInt(instance.currentColor)/255f, Color.greenFromInt(instance.currentColor)/255f, Color.blueFromInt(instance.currentColor)/255f, Color.alphaFromInt(instance.currentColor)/255f);
         shader.uniformFloat("uCurrentTick", instance.mc.ticksRan + instance.mc.timer.partialTicks);
@@ -355,6 +359,14 @@ public class GLRenderer {
         return instance.currentAlphaTest;
     }
 
+    public static void setLightMapStrength(float lightMapStrength) {
+        instance.currentLightMapStrength = lightMapStrength;
+    }
+
+    public static float getLightMapStrength() {
+        return instance.currentLightMapStrength;
+    }
+
     public static void setColor1i(int argb) {
         instance.currentColor = argb;
     }
@@ -427,6 +439,7 @@ public class GLRenderer {
         instance.polygonUnitsStack[instance.stackIndex] = instance.currentPolygonUnits;
         instance.lightIndexStack[instance.stackIndex] = instance.currentLightIndex;
         instance.alphaTestStack[instance.stackIndex] = instance.currentAlphaTest;
+        instance.lightMapStrengthStack[instance.stackIndex] = instance.currentLightMapStrength;
 
         if (DEBUG) {
             StackTraceElement[] eles = Thread.currentThread().getStackTrace();
@@ -527,6 +540,7 @@ public class GLRenderer {
 
         instance.currentLightIndex = instance.lightIndexStack[instance.stackIndex];
         instance.currentAlphaTest = instance.alphaTestStack[instance.stackIndex];
+        instance.currentLightMapStrength = instance.lightMapStrengthStack[instance.stackIndex];
     }
 
     protected static void reset() {
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/matcher/0.json b/game/client/src/main/resources/assets/minecraft/models/block/matcher/0.json
index 16603af3b..2ff2b2818 100644
--- a/game/client/src/main/resources/assets/minecraft/models/block/matcher/0.json
+++ b/game/client/src/main/resources/assets/minecraft/models/block/matcher/0.json
@@ -1,5 +1,5 @@
 {
-	"parent": "minecraft:block/cube_column",
+	"parent": "minecraft:block/matcher/template",
 	"textures": {
 		"end": "minecraft:block/matcher/front0",
 		"side": "minecraft:block/matcher/side"
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/matcher/1.json b/game/client/src/main/resources/assets/minecraft/models/block/matcher/1.json
index 4701d728a..0b26f42ad 100644
--- a/game/client/src/main/resources/assets/minecraft/models/block/matcher/1.json
+++ b/game/client/src/main/resources/assets/minecraft/models/block/matcher/1.json
@@ -1,5 +1,5 @@
 {
-	"parent": "minecraft:block/cube_column",
+	"parent": "minecraft:block/matcher/template",
 	"textures": {
 		"end": "minecraft:block/matcher/front1",
 		"side": "minecraft:block/matcher/side"
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/matcher/2.json b/game/client/src/main/resources/assets/minecraft/models/block/matcher/2.json
index c27a25f77..d923770e4 100644
--- a/game/client/src/main/resources/assets/minecraft/models/block/matcher/2.json
+++ b/game/client/src/main/resources/assets/minecraft/models/block/matcher/2.json
@@ -1,5 +1,5 @@
 {
-	"parent": "minecraft:block/cube_column",
+	"parent": "minecraft:block/matcher/template",
 	"textures": {
 		"end": "minecraft:block/matcher/front2",
 		"side": "minecraft:block/matcher/side"
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/matcher/3.json b/game/client/src/main/resources/assets/minecraft/models/block/matcher/3.json
index 5f4bc623d..a6ba65093 100644
--- a/game/client/src/main/resources/assets/minecraft/models/block/matcher/3.json
+++ b/game/client/src/main/resources/assets/minecraft/models/block/matcher/3.json
@@ -1,5 +1,5 @@
 {
-	"parent": "minecraft:block/cube_column",
+	"parent": "minecraft:block/matcher/template",
 	"textures": {
 		"end": "minecraft:block/matcher/front3",
 		"side": "minecraft:block/matcher/side"
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/matcher/active0.json b/game/client/src/main/resources/assets/minecraft/models/block/matcher/active0.json
index 914b3e633..27c1f6921 100644
--- a/game/client/src/main/resources/assets/minecraft/models/block/matcher/active0.json
+++ b/game/client/src/main/resources/assets/minecraft/models/block/matcher/active0.json
@@ -1,5 +1,5 @@
 {
-	"parent": "minecraft:block/cube_column",
+	"parent": "minecraft:block/matcher/template",
 	"textures": {
 		"end": "minecraft:block/matcher/front_active0",
 		"side": "minecraft:block/matcher/side_active"
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/matcher/active1.json b/game/client/src/main/resources/assets/minecraft/models/block/matcher/active1.json
index d25fad9bc..6f9393ca2 100644
--- a/game/client/src/main/resources/assets/minecraft/models/block/matcher/active1.json
+++ b/game/client/src/main/resources/assets/minecraft/models/block/matcher/active1.json
@@ -1,5 +1,5 @@
 {
-	"parent": "minecraft:block/cube_column",
+	"parent": "minecraft:block/matcher/template",
 	"textures": {
 		"end": "minecraft:block/matcher/front_active1",
 		"side": "minecraft:block/matcher/side_active"
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/matcher/active2.json b/game/client/src/main/resources/assets/minecraft/models/block/matcher/active2.json
index 068806ee2..6de35d34f 100644
--- a/game/client/src/main/resources/assets/minecraft/models/block/matcher/active2.json
+++ b/game/client/src/main/resources/assets/minecraft/models/block/matcher/active2.json
@@ -1,5 +1,5 @@
 {
-	"parent": "minecraft:block/cube_column",
+	"parent": "minecraft:block/matcher/template",
 	"textures": {
 		"end": "minecraft:block/matcher/front_active2",
 		"side": "minecraft:block/matcher/side_active"
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/matcher/active3.json b/game/client/src/main/resources/assets/minecraft/models/block/matcher/active3.json
index fb754ba60..2d71fc01a 100644
--- a/game/client/src/main/resources/assets/minecraft/models/block/matcher/active3.json
+++ b/game/client/src/main/resources/assets/minecraft/models/block/matcher/active3.json
@@ -1,5 +1,5 @@
 {
-	"parent": "minecraft:block/cube_column",
+	"parent": "minecraft:block/matcher/template",
 	"textures": {
 		"end": "minecraft:block/matcher/front_active3",
 		"side": "minecraft:block/matcher/side_active"
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/matcher/template.json b/game/client/src/main/resources/assets/minecraft/models/block/matcher/template.json
new file mode 100644
index 000000000..ed758f73b
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/block/matcher/template.json
@@ -0,0 +1,28 @@
+{
+	"format_version": "1.21.11",
+	"credit": "Made with Blockbench",
+	"parent": "block/block",
+	"textures": {
+		"overlay": "#end",
+		"particle_up": "#end",
+		"particle_down": "#end",
+		"particle_north": "#side",
+		"particle_south": "#side",
+		"particle_west": "#side",
+		"particle_east": "#side"
+	},
+	"elements": [
+		{
+			"from": [0, 0, 0],
+			"to": [16, 16, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 16, 16], "texture": "#side", "cullface": "north"},
+				"east": {"uv": [0, 0, 16, 16], "texture": "#side", "cullface": "east"},
+				"south": {"uv": [16, 0, 0, 16], "texture": "#side", "cullface": "south"},
+				"west": {"uv": [16, 0, 0, 16], "texture": "#side", "cullface": "west"},
+				"up": {"uv": [0, 0, 16, 16], "texture": "#end", "cullface": "up"},
+				"down": {"uv": [0, 16, 16, 0], "texture": "#end", "cullface": "down"}
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/basalt.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/basalt.png
index 7a81bf184..f82dc9152 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/basalt.png and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/basalt.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/gloomstone.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/gloomstone.png
index f45f1aef1..8c34adf09 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/gloomstone.png and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/gloomstone.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack.png
index bacb43b19..6c0338894 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack.png and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/item/rubyglass.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/item/rubyglass_crystal.emiss.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/item/rubyglass.emiss.png
rename to game/client/src/main/resources/assets/minecraft/textures/item/rubyglass_crystal.emiss.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/item/rubyglass.emiss.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/item/rubyglass_crystal.emiss.png.mcmeta
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/item/rubyglass.emiss.png.mcmeta
rename to game/client/src/main/resources/assets/minecraft/textures/item/rubyglass_crystal.emiss.png.mcmeta
diff --git a/game/client/src/main/resources/assets/minecraft/textures/item/rubyglass.png b/game/client/src/main/resources/assets/minecraft/textures/item/rubyglass_crystal.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/item/rubyglass.png
rename to game/client/src/main/resources/assets/minecraft/textures/item/rubyglass_crystal.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/item/rubyglass.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/item/rubyglass_crystal.png.mcmeta
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/item/rubyglass.png.mcmeta
rename to game/client/src/main/resources/assets/minecraft/textures/item/rubyglass_crystal.png.mcmeta
diff --git a/game/client/src/main/resources/assets/minecraft/textures/item/shard_rubyglass.png b/game/client/src/main/resources/assets/minecraft/textures/item/shard_rubyglass.png
deleted file mode 100644
index 10248c4c6..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/item/shard_rubyglass.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/item/tool_firestriker.png b/game/client/src/main/resources/assets/minecraft/textures/item/tool_firestriker_iron.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/item/tool_firestriker.png
rename to game/client/src/main/resources/assets/minecraft/textures/item/tool_firestriker_iron.png
diff --git a/game/client/src/main/resources/bg/adamng074_0.png b/game/client/src/main/resources/bg/adamng074_0.png
new file mode 100644
index 000000000..1ffc19a9d
Binary files /dev/null and b/game/client/src/main/resources/bg/adamng074_0.png differ
diff --git a/game/client/src/main/resources/bg/adamng074_1.png b/game/client/src/main/resources/bg/adamng074_1.png
new file mode 100644
index 000000000..d12797833
Binary files /dev/null and b/game/client/src/main/resources/bg/adamng074_1.png differ
diff --git a/game/client/src/main/resources/bg/adamng074_2.png b/game/client/src/main/resources/bg/adamng074_2.png
new file mode 100644
index 000000000..b30b27ba1
Binary files /dev/null and b/game/client/src/main/resources/bg/adamng074_2.png differ
diff --git a/game/client/src/main/resources/bg/armandothethird_0.png b/game/client/src/main/resources/bg/armandothethird_0.png
index b882e3be5..ef4195389 100644
Binary files a/game/client/src/main/resources/bg/armandothethird_0.png and b/game/client/src/main/resources/bg/armandothethird_0.png differ
diff --git a/game/client/src/main/resources/bg/armandothethird_1.png b/game/client/src/main/resources/bg/armandothethird_1.png
deleted file mode 100644
index 3396b717a..000000000
Binary files a/game/client/src/main/resources/bg/armandothethird_1.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/avix3212_0.png b/game/client/src/main/resources/bg/avix3212_0.png
deleted file mode 100644
index f0744ecae..000000000
Binary files a/game/client/src/main/resources/bg/avix3212_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/backgrounds.json b/game/client/src/main/resources/bg/backgrounds.json
index 4e175900f..fee7b8428 100644
--- a/game/client/src/main/resources/bg/backgrounds.json
+++ b/game/client/src/main/resources/bg/backgrounds.json
@@ -1,38 +1,38 @@
 {
 	"replace": false,
 	"backgrounds": [
+		"adamng074_0",
+		"adamng074_1",
+		"adamng074_2",
 		"armandothethird_0",
-		"armandothethird_1",
-		"avix3212_0",
-		"betmu_0",
-		"captus04_0",
-		"dakras_0",
-		"floralz_0",
-		"frazzelbones_0",
-		"hen0tic02_0",
-		"hobblerox_0",
-		"hobblerox_1",
-		"hydracl_0",
-		"ikkykrrk_0",
-		"itsifox_0",
-		"kiwind._0",
-		"kristality_0",
-		"pyromancer___0",
+		"brokendoop_0",
+		"camoweed__0",
+		"chlo_the_doe_0",
+		"gratedparmesan_0",
+		"kyishka_0",
+		"lilac.shades_0",
+		"lostglaceon_0",
+		"lostglaceon_1",
+		"lux64_0",
+		"lux64_1",
+		"phoebruary_0",
+		"phoebruary_1",
 		"redslimeeee_0",
-		"sinecaus_0",
-		"sinecaus_1",
-		"sinecaus_2",
+		"sabanii_0",
 		"snek8611_0",
-		"sourzombo_0",
-		"sx22_0",
-		"sx22_1",
-		"t3ssed_0",
-		"t3ssed_1",
-		"t3ssed_2",
-		"thaboar_0",
-		"thaboar_1",
+		"soupamng_0",
+		"telvasyl_0",
+		"telvasyl_1",
+		"tenma_gabriel_0",
+		"tenma_gabriel_1",
+		"timtams_1",
 		"timtams72_0",
-		"timtams72_1",
-		"wwolflesbian_0"
+		"w1nw1n_0",
+		"w1nw1n_1",
+		"wildedit_0",
+		"wildedit_1",
+		"wildedit_2",
+		"wildedit_3",
+		"yojin_0_0",
 	]
 }
diff --git a/game/client/src/main/resources/bg/betmu_0.png b/game/client/src/main/resources/bg/betmu_0.png
deleted file mode 100644
index bfb9e30f8..000000000
Binary files a/game/client/src/main/resources/bg/betmu_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/brokendoop_0.png b/game/client/src/main/resources/bg/brokendoop_0.png
new file mode 100644
index 000000000..51b7b5ab6
Binary files /dev/null and b/game/client/src/main/resources/bg/brokendoop_0.png differ
diff --git a/game/client/src/main/resources/bg/camoweed__0.png b/game/client/src/main/resources/bg/camoweed__0.png
new file mode 100644
index 000000000..ecb57f0f1
Binary files /dev/null and b/game/client/src/main/resources/bg/camoweed__0.png differ
diff --git a/game/client/src/main/resources/bg/captus04_0.png b/game/client/src/main/resources/bg/captus04_0.png
deleted file mode 100644
index ca37781f5..000000000
Binary files a/game/client/src/main/resources/bg/captus04_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/chlo_the_doe_0.png b/game/client/src/main/resources/bg/chlo_the_doe_0.png
new file mode 100644
index 000000000..de54d9505
Binary files /dev/null and b/game/client/src/main/resources/bg/chlo_the_doe_0.png differ
diff --git a/game/client/src/main/resources/bg/dakras_0.png b/game/client/src/main/resources/bg/dakras_0.png
deleted file mode 100644
index 86d7e7451..000000000
Binary files a/game/client/src/main/resources/bg/dakras_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/floralz_0.png b/game/client/src/main/resources/bg/floralz_0.png
deleted file mode 100644
index a20dcb800..000000000
Binary files a/game/client/src/main/resources/bg/floralz_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/frazzelbones_0.png b/game/client/src/main/resources/bg/frazzelbones_0.png
deleted file mode 100644
index 06b0c8544..000000000
Binary files a/game/client/src/main/resources/bg/frazzelbones_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/gratedparmesan_0.png b/game/client/src/main/resources/bg/gratedparmesan_0.png
new file mode 100644
index 000000000..3b84f19b4
Binary files /dev/null and b/game/client/src/main/resources/bg/gratedparmesan_0.png differ
diff --git a/game/client/src/main/resources/bg/hen0tic02_0.png b/game/client/src/main/resources/bg/hen0tic02_0.png
deleted file mode 100644
index a4693680d..000000000
Binary files a/game/client/src/main/resources/bg/hen0tic02_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/hobblerox_0.png b/game/client/src/main/resources/bg/hobblerox_0.png
deleted file mode 100644
index 6002160ad..000000000
Binary files a/game/client/src/main/resources/bg/hobblerox_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/hobblerox_1.png b/game/client/src/main/resources/bg/hobblerox_1.png
deleted file mode 100644
index 25ac6f42e..000000000
Binary files a/game/client/src/main/resources/bg/hobblerox_1.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/hydracl_0.png b/game/client/src/main/resources/bg/hydracl_0.png
deleted file mode 100644
index c190977ad..000000000
Binary files a/game/client/src/main/resources/bg/hydracl_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/ikkykrrk_0.png b/game/client/src/main/resources/bg/ikkykrrk_0.png
deleted file mode 100644
index 72b0ec7aa..000000000
Binary files a/game/client/src/main/resources/bg/ikkykrrk_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/itsifox_0.png b/game/client/src/main/resources/bg/itsifox_0.png
deleted file mode 100644
index 160e760f0..000000000
Binary files a/game/client/src/main/resources/bg/itsifox_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/kiwind._0.png b/game/client/src/main/resources/bg/kiwind._0.png
deleted file mode 100644
index 94f89423d..000000000
Binary files a/game/client/src/main/resources/bg/kiwind._0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/kristality_0.png b/game/client/src/main/resources/bg/kristality_0.png
deleted file mode 100644
index b73cb2bbf..000000000
Binary files a/game/client/src/main/resources/bg/kristality_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/kyishka_0.png b/game/client/src/main/resources/bg/kyishka_0.png
new file mode 100644
index 000000000..f3aa92aca
Binary files /dev/null and b/game/client/src/main/resources/bg/kyishka_0.png differ
diff --git a/game/client/src/main/resources/bg/lilac.shades_0.png b/game/client/src/main/resources/bg/lilac.shades_0.png
new file mode 100644
index 000000000..9c0957955
Binary files /dev/null and b/game/client/src/main/resources/bg/lilac.shades_0.png differ
diff --git a/game/client/src/main/resources/bg/lostglaceon_0.png b/game/client/src/main/resources/bg/lostglaceon_0.png
new file mode 100644
index 000000000..262643c0f
Binary files /dev/null and b/game/client/src/main/resources/bg/lostglaceon_0.png differ
diff --git a/game/client/src/main/resources/bg/lostglaceon_1.png b/game/client/src/main/resources/bg/lostglaceon_1.png
new file mode 100644
index 000000000..b234cbde6
Binary files /dev/null and b/game/client/src/main/resources/bg/lostglaceon_1.png differ
diff --git a/game/client/src/main/resources/bg/lux64_0.png b/game/client/src/main/resources/bg/lux64_0.png
new file mode 100644
index 000000000..50ca3853a
Binary files /dev/null and b/game/client/src/main/resources/bg/lux64_0.png differ
diff --git a/game/client/src/main/resources/bg/lux64_1.png b/game/client/src/main/resources/bg/lux64_1.png
new file mode 100644
index 000000000..5fc8afa75
Binary files /dev/null and b/game/client/src/main/resources/bg/lux64_1.png differ
diff --git a/game/client/src/main/resources/bg/phoebruary_0.png b/game/client/src/main/resources/bg/phoebruary_0.png
new file mode 100644
index 000000000..57c671684
Binary files /dev/null and b/game/client/src/main/resources/bg/phoebruary_0.png differ
diff --git a/game/client/src/main/resources/bg/phoebruary_1.png b/game/client/src/main/resources/bg/phoebruary_1.png
new file mode 100644
index 000000000..bb9090220
Binary files /dev/null and b/game/client/src/main/resources/bg/phoebruary_1.png differ
diff --git a/game/client/src/main/resources/bg/pyromancer___0.png b/game/client/src/main/resources/bg/pyromancer___0.png
deleted file mode 100644
index a4ab1f7f1..000000000
Binary files a/game/client/src/main/resources/bg/pyromancer___0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/redslimeeee_0.png b/game/client/src/main/resources/bg/redslimeeee_0.png
index 0e6328661..7c816241a 100644
Binary files a/game/client/src/main/resources/bg/redslimeeee_0.png and b/game/client/src/main/resources/bg/redslimeeee_0.png differ
diff --git a/game/client/src/main/resources/bg/sabanii_0.png b/game/client/src/main/resources/bg/sabanii_0.png
new file mode 100644
index 000000000..cfc2f29d2
Binary files /dev/null and b/game/client/src/main/resources/bg/sabanii_0.png differ
diff --git a/game/client/src/main/resources/bg/sinecaus_0.png b/game/client/src/main/resources/bg/sinecaus_0.png
deleted file mode 100644
index e25226452..000000000
Binary files a/game/client/src/main/resources/bg/sinecaus_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/sinecaus_1.png b/game/client/src/main/resources/bg/sinecaus_1.png
deleted file mode 100644
index d5b3345f7..000000000
Binary files a/game/client/src/main/resources/bg/sinecaus_1.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/sinecaus_2.png b/game/client/src/main/resources/bg/sinecaus_2.png
deleted file mode 100644
index ea5e01a45..000000000
Binary files a/game/client/src/main/resources/bg/sinecaus_2.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/snek8611_0.png b/game/client/src/main/resources/bg/snek8611_0.png
index 731b658ef..b78b3588e 100644
Binary files a/game/client/src/main/resources/bg/snek8611_0.png and b/game/client/src/main/resources/bg/snek8611_0.png differ
diff --git a/game/client/src/main/resources/bg/soupamng_0.png b/game/client/src/main/resources/bg/soupamng_0.png
new file mode 100644
index 000000000..43a2eeb53
Binary files /dev/null and b/game/client/src/main/resources/bg/soupamng_0.png differ
diff --git a/game/client/src/main/resources/bg/sourzombo_0.png b/game/client/src/main/resources/bg/sourzombo_0.png
deleted file mode 100644
index 9149b0c1d..000000000
Binary files a/game/client/src/main/resources/bg/sourzombo_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/sx22_0.png b/game/client/src/main/resources/bg/sx22_0.png
deleted file mode 100644
index 506ff10ac..000000000
Binary files a/game/client/src/main/resources/bg/sx22_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/sx22_1.png b/game/client/src/main/resources/bg/sx22_1.png
deleted file mode 100644
index 171b2a816..000000000
Binary files a/game/client/src/main/resources/bg/sx22_1.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/t3ssed_0.png b/game/client/src/main/resources/bg/t3ssed_0.png
deleted file mode 100644
index 3c06ce6e6..000000000
Binary files a/game/client/src/main/resources/bg/t3ssed_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/t3ssed_1.png b/game/client/src/main/resources/bg/t3ssed_1.png
deleted file mode 100644
index 028694219..000000000
Binary files a/game/client/src/main/resources/bg/t3ssed_1.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/t3ssed_2.png b/game/client/src/main/resources/bg/t3ssed_2.png
deleted file mode 100644
index aee6b73d5..000000000
Binary files a/game/client/src/main/resources/bg/t3ssed_2.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/telvasyl_0.png b/game/client/src/main/resources/bg/telvasyl_0.png
new file mode 100644
index 000000000..7626cd834
Binary files /dev/null and b/game/client/src/main/resources/bg/telvasyl_0.png differ
diff --git a/game/client/src/main/resources/bg/telvasyl_1.png b/game/client/src/main/resources/bg/telvasyl_1.png
new file mode 100644
index 000000000..e8647bdc5
Binary files /dev/null and b/game/client/src/main/resources/bg/telvasyl_1.png differ
diff --git a/game/client/src/main/resources/bg/tenma_gabriel_0.png b/game/client/src/main/resources/bg/tenma_gabriel_0.png
new file mode 100644
index 000000000..75ff5ae6c
Binary files /dev/null and b/game/client/src/main/resources/bg/tenma_gabriel_0.png differ
diff --git a/game/client/src/main/resources/bg/tenma_gabriel_1.png b/game/client/src/main/resources/bg/tenma_gabriel_1.png
new file mode 100644
index 000000000..35db5c3d9
Binary files /dev/null and b/game/client/src/main/resources/bg/tenma_gabriel_1.png differ
diff --git a/game/client/src/main/resources/bg/thaboar_0.png b/game/client/src/main/resources/bg/thaboar_0.png
deleted file mode 100644
index bc950ff7e..000000000
Binary files a/game/client/src/main/resources/bg/thaboar_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/thaboar_1.png b/game/client/src/main/resources/bg/thaboar_1.png
deleted file mode 100644
index bb5d8dbcf..000000000
Binary files a/game/client/src/main/resources/bg/thaboar_1.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/timtams72_0.png b/game/client/src/main/resources/bg/timtams72_0.png
index b5cfc5a6d..56c0b1a4a 100644
Binary files a/game/client/src/main/resources/bg/timtams72_0.png and b/game/client/src/main/resources/bg/timtams72_0.png differ
diff --git a/game/client/src/main/resources/bg/timtams72_1.png b/game/client/src/main/resources/bg/timtams72_1.png
deleted file mode 100644
index 72bd22187..000000000
Binary files a/game/client/src/main/resources/bg/timtams72_1.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/timtams_1.png b/game/client/src/main/resources/bg/timtams_1.png
new file mode 100644
index 000000000..14a0957f0
Binary files /dev/null and b/game/client/src/main/resources/bg/timtams_1.png differ
diff --git a/game/client/src/main/resources/bg/w1nw1n_0.png b/game/client/src/main/resources/bg/w1nw1n_0.png
new file mode 100644
index 000000000..6fa6c8169
Binary files /dev/null and b/game/client/src/main/resources/bg/w1nw1n_0.png differ
diff --git a/game/client/src/main/resources/bg/w1nw1n_1.png b/game/client/src/main/resources/bg/w1nw1n_1.png
new file mode 100644
index 000000000..437d2a2ef
Binary files /dev/null and b/game/client/src/main/resources/bg/w1nw1n_1.png differ
diff --git a/game/client/src/main/resources/bg/wildedit_0.png b/game/client/src/main/resources/bg/wildedit_0.png
new file mode 100644
index 000000000..c0b4d6e27
Binary files /dev/null and b/game/client/src/main/resources/bg/wildedit_0.png differ
diff --git a/game/client/src/main/resources/bg/wildedit_1.png b/game/client/src/main/resources/bg/wildedit_1.png
new file mode 100644
index 000000000..2e295346f
Binary files /dev/null and b/game/client/src/main/resources/bg/wildedit_1.png differ
diff --git a/game/client/src/main/resources/bg/wildedit_2.png b/game/client/src/main/resources/bg/wildedit_2.png
new file mode 100644
index 000000000..78cd0085a
Binary files /dev/null and b/game/client/src/main/resources/bg/wildedit_2.png differ
diff --git a/game/client/src/main/resources/bg/wildedit_3.png b/game/client/src/main/resources/bg/wildedit_3.png
new file mode 100644
index 000000000..ca6bc4fd1
Binary files /dev/null and b/game/client/src/main/resources/bg/wildedit_3.png differ
diff --git a/game/client/src/main/resources/bg/wwolflesbian_0.png b/game/client/src/main/resources/bg/wwolflesbian_0.png
deleted file mode 100644
index eb549e30b..000000000
Binary files a/game/client/src/main/resources/bg/wwolflesbian_0.png and /dev/null differ
diff --git a/game/client/src/main/resources/bg/yojin_0_0.png b/game/client/src/main/resources/bg/yojin_0_0.png
new file mode 100644
index 000000000..e65ad5136
Binary files /dev/null and b/game/client/src/main/resources/bg/yojin_0_0.png differ
diff --git a/game/client/src/main/resources/shaders/color_world.fsh b/game/client/src/main/resources/shaders/color_world.fsh
index dfd85c2ff..d67aea9e1 100644
--- a/game/client/src/main/resources/shaders/color_world.fsh
+++ b/game/client/src/main/resources/shaders/color_world.fsh
@@ -6,6 +6,7 @@ in vec4 Color;
 in vec2 LightMapCoord;
 in vec3 Light;
 
+uniform float uLightMapStrength;
 uniform float uAlphaTest;
 uniform vec4 uColor;
 uniform vec2 uViewPortSize;
@@ -65,7 +66,7 @@ vec4 computeFog(vec4 color) {
 }
 
 void main() {
-    vec4 lightColor = texture(lighttex, LightMapCoord);
+    vec4 lightColor = mix(vec4(1, 1, 1, 1), texture(lighttex, LightMapCoord), uLightMapStrength);
 
     vec4 oColor = lightColor * Color * uColor;
     vec4 litColor = vec4(oColor.rgb * clamp(Light, 0, 1), oColor.a);
diff --git a/game/client/src/main/resources/shaders/entity.fsh b/game/client/src/main/resources/shaders/entity.fsh
index 380af1944..fdaca5df0 100644
--- a/game/client/src/main/resources/shaders/entity.fsh
+++ b/game/client/src/main/resources/shaders/entity.fsh
@@ -5,6 +5,7 @@ out vec4 FragColor;
 in vec2 TexCoord;
 in vec3 Light;
 
+uniform float uLightMapStrength;
 uniform float uAlphaTest;
 uniform vec4 uColor;
 uniform vec2 uLightmap;
@@ -66,7 +67,7 @@ vec4 computeFog(vec4 color) {
 }
 
 void main() {
-    vec4 lightColor = texture(lighttex, uLightmap);
+    vec4 lightColor = mix(vec4(1, 1, 1, 1), texture(lighttex, uLightmap), uLightMapStrength);
     vec4 texColor = texture(colortex, TexCoord);
 
     vec4 oColor = texColor * lightColor * uColor;
diff --git a/game/client/src/main/resources/shaders/font.fsh b/game/client/src/main/resources/shaders/font.fsh
index 769eaa3dd..d86522da3 100644
--- a/game/client/src/main/resources/shaders/font.fsh
+++ b/game/client/src/main/resources/shaders/font.fsh
@@ -22,6 +22,7 @@ in vec2 Size;
 in float Config;
 
 uniform float uAlphaTest;
+uniform float uLightMapStrength;
 uniform vec4 uColor;
 
 uniform sampler2D colortex;
@@ -51,9 +52,8 @@ vec4 bold(vec2 coord, vec4 text, vec4 textColor)
 	return text;
 }
 
-vec4 colorAtPoint(vec2 point) {
+vec4 colorAtPoint(vec2 point, vec4 tint) {
     uint config = uint(Config + 0.01);
-    vec4 tint = texture(lighttex, Lightmap) * uColor;
 
     vec4 color = vec4(0);
     if (sampleInside(point)) {
@@ -74,17 +74,17 @@ vec4 colorAtPoint(vec2 point) {
     return color;
 }
 
-bool canReplace(vec2 tex) {
-    vec4 c = colorAtPoint(tex);
+bool canReplace(vec2 tex, vec4 tint) {
+    vec4 c = colorAtPoint(tex, tint);
     return c.a > 0.1;
 }
 
-float outline()
+float outline(vec4 tint)
 {
 	for(int x = -sh.x; x <= sh.x; x++)
 	for(int y = -sh.y; y <= sh.y; y++)
 	{
-		if(canReplace(TexCoord + vec2(x,y)/rh)) return 1.0f;
+		if(canReplace(TexCoord + vec2(x,y)/rh, tint)) return 1.0f;
 	}
 
 	return 0.0f;
@@ -92,15 +92,15 @@ float outline()
 
 void main() {
     uint config = uint(Config + 0.01);
-    vec4 tint = texture(lighttex, Lightmap) * uColor;
-    FragColor = colorAtPoint(TexCoord);
+    vec4 tint = mix(vec4(1, 1, 1, 1), texture(lighttex, Lightmap), uLightMapStrength) * uColor;
+    FragColor = colorAtPoint(TexCoord, tint);
 	
     if (FragColor.a < 0.1) {
         if ((config & MASK_OUTLINE) != 0) {
-			FragColor = vec4(Color.rgb/4, Color.a) * tint * outline();
+			FragColor = vec4(Color.rgb/4, Color.a) * tint * outline(tint);
         } else if ((config & MASK_SHADOW) != 0) {
             vec2 upLeft = TexCoord - vec2(1, 1)/F_PIX;
-            if (canReplace(upLeft)) {
+            if (canReplace(upLeft, tint)) {
                 FragColor = vec4(Color.rgb/4, Color.a) * tint;
             }
         }
diff --git a/game/client/src/main/resources/shaders/item.fsh b/game/client/src/main/resources/shaders/item.fsh
index a4e565f79..af27bde3e 100644
--- a/game/client/src/main/resources/shaders/item.fsh
+++ b/game/client/src/main/resources/shaders/item.fsh
@@ -8,6 +8,7 @@ in vec2 LightMapCoord;
 in vec3 Light;
 in vec3 Norm;
 
+uniform float uLightMapStrength;
 uniform float uAlphaTest;
 uniform vec4 uColor;
 uniform vec2 uViewPortSize;
@@ -71,7 +72,7 @@ vec4 computeFog(vec4 color) {
 
 void main() {
     vec2 emissiveBrightness = texture(emissivetex, TexCoord).xy;
-    vec4 lightColor = texture(lighttex, vec2(max(LightMapCoord.x, emissiveBrightness.x), max(LightMapCoord.y, emissiveBrightness.y)));
+    vec4 lightColor = mix(vec4(1, 1, 1, 1), texture(lighttex, vec2(max(LightMapCoord.x, emissiveBrightness.x), max(LightMapCoord.y, emissiveBrightness.y))), uLightMapStrength);
     vec4 texColor = texture(colortex, TexCoord);
     vec4 maskColor = texture(colormasktex, TexCoord);
 
diff --git a/game/client/src/main/resources/shaders/particle.fsh b/game/client/src/main/resources/shaders/particle.fsh
index e29b9cbeb..2eb502b1b 100644
--- a/game/client/src/main/resources/shaders/particle.fsh
+++ b/game/client/src/main/resources/shaders/particle.fsh
@@ -5,6 +5,7 @@ in vec4 Color;
 in vec2 TexCoord;
 in vec2 LightMapCoord;
 
+uniform float uLightMapStrength;
 uniform float uAlphaTest;
 uniform vec4 uColor;
 uniform vec2 uViewPortSize;
@@ -68,7 +69,7 @@ vec4 computeFog(vec4 color) {
 
 void main() {
     vec2 emissiveBrightness = texture(emissivetex, TexCoord).xy;
-    vec4 lightColor = texture(lighttex, vec2(max(LightMapCoord.x, emissiveBrightness.x), max(LightMapCoord.y, emissiveBrightness.y)));
+    vec4 lightColor = mix(vec4(1, 1, 1, 1), texture(lighttex, vec2(max(LightMapCoord.x, emissiveBrightness.x), max(LightMapCoord.y, emissiveBrightness.y))), uLightMapStrength);
     vec4 texColor = texture(colortex, TexCoord);
     vec4 maskColor = texture(colormasktex, TexCoord);
 
diff --git a/game/client/src/main/resources/shaders/terrain.fsh b/game/client/src/main/resources/shaders/terrain.fsh
index ce9aaa24d..bad168a16 100644
--- a/game/client/src/main/resources/shaders/terrain.fsh
+++ b/game/client/src/main/resources/shaders/terrain.fsh
@@ -9,6 +9,7 @@ in vec2 LightMapCoord;
 in vec3 Light;
 in vec4 Norm;
 
+uniform float uLightMapStrength;
 uniform float uAlphaTest;
 uniform vec4 uColor;
 uniform vec2 uViewPortSize;
@@ -72,7 +73,7 @@ vec4 computeFog(vec4 color) {
 
 void main() {
     vec2 emissiveBrightness = texture(emissivetex, TexCoord).xy;
-    vec4 lightColor = texture(lighttex, vec2(max(LightMapCoord.x, emissiveBrightness.x), max(LightMapCoord.y, emissiveBrightness.y)));
+    vec4 lightColor = mix(vec4(1, 1, 1, 1), texture(lighttex, vec2(max(LightMapCoord.x, emissiveBrightness.x), max(LightMapCoord.y, emissiveBrightness.y))), uLightMapStrength);
     vec4 texColor = texture(colortex, TexCoord);
     vec4 maskColor = texture(colormasktex, TexCoord);
 
diff --git a/game/client/src/main/resources/shaders/world.fsh b/game/client/src/main/resources/shaders/world.fsh
index 990459bfb..0e7431719 100644
--- a/game/client/src/main/resources/shaders/world.fsh
+++ b/game/client/src/main/resources/shaders/world.fsh
@@ -7,6 +7,7 @@ in vec2 TexCoord;
 in vec2 LightMapCoord;
 in vec3 Light;
 
+uniform float uLightMapStrength;
 uniform float uAlphaTest;
 uniform vec4 uColor;
 uniform vec2 uViewPortSize;
@@ -67,7 +68,7 @@ vec4 computeFog(vec4 color) {
 }
 
 void main() {
-    vec4 lightColor = texture(lighttex, LightMapCoord);
+    vec4 lightColor = mix(vec4(1, 1, 1, 1), texture(lighttex, LightMapCoord), uLightMapStrength);
     vec4 texColor = texture(colortex, TexCoord);
 
     vec4 oColor = texColor * lightColor * Color * uColor;
diff --git a/game/core/src/main/java/net/minecraft/core/Global.java b/game/core/src/main/java/net/minecraft/core/Global.java
index e52cbd558..fe2859e01 100644
--- a/game/core/src/main/java/net/minecraft/core/Global.java
+++ b/game/core/src/main/java/net/minecraft/core/Global.java
@@ -8,7 +8,7 @@ public class Global
 	public static final int DAY_LENGTH_TICKS = 24000;
 	public static final @NotNull String VERSION = Version.BUILD_CHANNEL.modifyVersionString(Version.VERSION);
 	public static final @NotNull BuildChannel BUILD_CHANNEL = Version.BUILD_CHANNEL;
-	public static final int CURRENT_SAVE_VERSION = 19135;
+	public static final int CURRENT_SAVE_VERSION = 19136;
 	public static final int CURRENT_CHUNK_VERSION = 3;
 	public static boolean isServer = false;
 	public static final boolean DISABLE_OLD_WORLDS = false;
diff --git a/game/core/src/main/java/net/minecraft/core/block/Block.java b/game/core/src/main/java/net/minecraft/core/block/Block.java
index af0cb7f8e..507972aca 100644
--- a/game/core/src/main/java/net/minecraft/core/block/Block.java
+++ b/game/core/src/main/java/net/minecraft/core/block/Block.java
@@ -62,7 +62,6 @@ public final class Block<T extends BlockLogic>
     public float friction;
     public int emission;
     public @Nullable Integer lightBlock = null;
-    public boolean immovable = false;
     public boolean isEntityTile = false;
     public boolean disabledNeighborMetaNotify = false;
     public boolean shouldTick = false;
@@ -82,7 +81,6 @@ public final class Block<T extends BlockLogic>
         this.enableStats = true;
         this.blockParticleGravity = 1.0F;
         this.friction = 0.6F;
-        this.immovable = false;
     }
 
     private int setupNumericId(final int id) {
@@ -150,11 +148,6 @@ public final class Block<T extends BlockLogic>
         return this;
     }
 
-    public Block<T> withImmovableFlagSet() {
-        this.immovable = true;
-        return this;
-    }
-
     public Block<T> withBlastResistance(final float blastResistance) {
         this.blastResistance = blastResistance * 3F;
         return this;
@@ -451,11 +444,6 @@ public final class Block<T extends BlockLogic>
         return this.logic.getStrength(world, tilePos, side, player);
     }
 
-    @Override
-    public boolean getImmovable() {
-        return this.logic.getImmovable();
-    }
-
     @Override
     public float getBlastResistance(final @Nullable Entity entity) {
         return this.logic.getBlastResistance(entity);
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 cb1924579..d161131d3 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
@@ -209,8 +209,6 @@ interface BlockInterface {
         return this.getStrength(world, new TilePos(x, y, z), side, player);
     }
 
-    boolean getImmovable();
-
     float getBlastResistance(final @Nullable Entity entity);
 
     @Nullable HitResult collisionRayTrace(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Vector3dc start, final @NotNull Vector3dc end, final boolean useSelectionAABB);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java
index 8c5147655..b710ae394 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java
@@ -271,11 +271,6 @@ public class BlockLogic implements BlockInterface, IItemConvertible {
         }
     }
 
-    @Override
-    public boolean getImmovable() {
-        return this.block.immovable;
-    }
-
     @Override
     public float getBlastResistance(final @Nullable Entity entity) {
         return this.block.blastResistance / 5f;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicAir.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicAir.java
index 93f4ffb1d..f8fe18d53 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicAir.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicAir.java
@@ -82,11 +82,6 @@ public class BlockLogicAir
         return 0.0f;
     }
 
-    @Override
-    public boolean getImmovable() {
-        return false;
-    }
-
     @Override
     public float getBlastResistance(final @Nullable Entity entity) {
         return 0.0f;
@@ -121,4 +116,9 @@ public class BlockLogicAir
     public @NotNull ISupport getSupport(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Side side) {
         return PartialSupport.INSTANCE;
     }
+
+    @Override
+    public int getPistonPushReaction(@NotNull World world, @NotNull TilePosc tilePos) {
+        return Material.PISTON_DESTROY_ON_PUSH;
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java
index f436e5c64..2b53b79d0 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBedrock.java
@@ -34,4 +34,9 @@ public class BlockLogicBedrock
         final var thatguy = world.getClosestPlayerToEntity(thisguy, 16D);
         if (thatguy != null) thisguy.hurt(thatguy, 1, DamageType.GENERIC);
     }
+
+    @Override
+    public int getPistonPushReaction(@NotNull World world, @NotNull TilePosc tilePos) {
+        return Material.PISTON_CANT_PUSH;
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBonePile.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBonePile.java
index 84c3ebcb3..905f1514f 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBonePile.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBonePile.java
@@ -34,7 +34,7 @@ public class BlockLogicBonePile
         return switch (dropCause) {
             case SILK_TOUCH, PICK_BLOCK -> new ItemStack[] { new ItemStack(this) };
             default -> {
-                int dropChance = 5;
+                int dropChance = 4;
                 if (world.rand.nextInt(dropChance) == 0) {
                     yield new ItemStack[] { new ItemStack(Items.BONE, 1) };
                 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoneShale.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoneShale.java
index deba70176..4924b90f7 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoneShale.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoneShale.java
@@ -30,4 +30,9 @@ public class BlockLogicBoneShale
             return player.getCurrentPlayerStrVsBlock(this.block) / blockHardness / 30F;
         }
     }
+
+    @Override
+    public int getPistonPushReaction(@NotNull World world, @NotNull TilePosc tilePos) {
+        return Material.PISTON_CANT_PUSH;
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoulderMagmatic.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoulderMagmatic.java
index 4c551034a..72ba7bf14 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoulderMagmatic.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoulderMagmatic.java
@@ -3,6 +3,7 @@ package net.minecraft.core.block;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.enums.EnumDropCause;
+import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.pos.TilePos;
@@ -37,7 +38,13 @@ public class BlockLogicBoulderMagmatic extends BlockLogicFlower {
 	public @NotNull ItemStack @Nullable [] getBreakResult(@NotNull World world, @NotNull EnumDropCause dropCause, int meta, @Nullable TileEntity tileEntity) {
 		return switch (dropCause) {
 			case SILK_TOUCH, PICK_BLOCK -> new ItemStack[]{new ItemStack(this)};
-			default -> null;
+			default -> {
+				final int pebbles = 1 + world.rand.nextInt(2);
+				if (world.rand.nextInt(4) == 0) {
+					yield new ItemStack[]{new ItemStack(Items.AMMO_PEBBLE, pebbles), new ItemStack(Items.NETHERCOAL)};
+				}
+				yield new ItemStack[]{new ItemStack(Items.AMMO_PEBBLE, pebbles)};
+			}
 		};
 	}
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoulderSulfuric.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoulderSulfuric.java
index 5fcbe3029..6791d070b 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoulderSulfuric.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBoulderSulfuric.java
@@ -1,9 +1,14 @@
 package net.minecraft.core.block;
 
+import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.Entity;
+import net.minecraft.core.enums.EnumDropCause;
+import net.minecraft.core.item.Items;
+import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.pos.TilePosc;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class BlockLogicBoulderSulfuric extends BlockLogicBoulderMagmatic {
 	public BlockLogicBoulderSulfuric(@NotNull Block<?> block) {
@@ -11,6 +16,20 @@ public class BlockLogicBoulderSulfuric extends BlockLogicBoulderMagmatic {
 		this.setBlockBounds(0.1F, 0.0F, 0.1F, 0.9F, 0.8F, 0.9F);
 	}
 
+	@Override
+	public @NotNull ItemStack @Nullable [] getBreakResult(@NotNull World world, @NotNull EnumDropCause dropCause, int meta, @Nullable TileEntity tileEntity) {
+		return switch (dropCause) {
+			case SILK_TOUCH, PICK_BLOCK -> new ItemStack[]{new ItemStack(this)};
+			default -> {
+				final int pebbles = 1 + world.rand.nextInt(2);
+				if (world.rand.nextInt(4) == 0) {
+					yield new ItemStack[]{new ItemStack(Items.AMMO_PEBBLE, pebbles), new ItemStack(Items.SULFUR)};
+				}
+				yield new ItemStack[]{new ItemStack(Items.AMMO_PEBBLE, pebbles)};
+			}
+		};
+	}
+
 	@Override
 	public void onEntityCollision(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Entity entity) {
 		entity.maxFireTicks = 100;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicButton.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicButton.java
index 84e005a2d..b8add79b1 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicButton.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicButton.java
@@ -342,7 +342,7 @@ public class BlockLogicButton
 
     @Override
     public boolean canBePainted() {
-        return this.id() == Blocks.BUTTON_PLANKS.id();
+        return this.id() == Blocks.BUTTON_PLANKS_OAK.id();
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPainted.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPainted.java
index b899abe2b..72252d6e2 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPainted.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPainted.java
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class BlockLogicButtonPainted
-    extends BlockLogicButtonPlanks
+    extends BlockLogicButtonPlanksOak
     implements IPainted {
     public static final int MASK_COLOR = 0b1111_0000;
 
@@ -47,7 +47,7 @@ public class BlockLogicButtonPainted
 
     @Override
     public void removeDye(final @NotNull World world, final @NotNull TilePosc tilePos) {
-        world.setBlockTypeNotify(tilePos, Blocks.BUTTON_PLANKS);
+        world.setBlockTypeNotify(tilePos, Blocks.BUTTON_PLANKS_OAK);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPlanks.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPlanks.java
deleted file mode 100644
index b9cc614dd..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPlanks.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.entity.TileEntity;
-import net.minecraft.core.block.entity.TileEntityActivator;
-import net.minecraft.core.block.material.Material;
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.player.Player;
-import net.minecraft.core.enums.EnumDropCause;
-import net.minecraft.core.item.Item;
-import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.item.tag.ItemTags;
-import net.minecraft.core.sound.SoundCategory;
-import net.minecraft.core.util.helper.Direction;
-import net.minecraft.core.util.helper.DyeColor;
-import net.minecraft.core.util.helper.Side;
-import net.minecraft.core.world.World;
-import net.minecraft.core.world.WorldSource;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Random;
-
-public class BlockLogicButtonPlanks
-    extends BlockLogicButton {
-
-    public BlockLogicButtonPlanks(final @NotNull Block<?> block) {
-        super(block);
-    }
-
-    @Override
-    public int tickDelay() {
-        return 10;
-    }
-
-}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPlanksOak.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPlanksOak.java
new file mode 100644
index 000000000..d8d4ad263
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicButtonPlanksOak.java
@@ -0,0 +1,17 @@
+package net.minecraft.core.block;
+
+import org.jetbrains.annotations.NotNull;
+
+public class BlockLogicButtonPlanksOak
+    extends BlockLogicButton {
+
+    public BlockLogicButtonPlanksOak(final @NotNull Block<?> block) {
+        super(block);
+    }
+
+    @Override
+    public int tickDelay() {
+        return 10;
+    }
+
+}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java
index 9372320e5..53b5267a0 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java
@@ -224,7 +224,14 @@ public class BlockLogicFire
     private void checkBurn(final @NotNull World world, final @NotNull TilePos tilePos, final int chance, final @NotNull Random random, final int meta) {
         if (!world.getGameRuleValue(GameRules.DO_FIRE_SPREAD)) return;
         if (random.nextInt(chance) < burnChance[world.getBlockType(tilePos).id()]) {
-            final boolean isTNT = world.getBlockType(tilePos) == Blocks.TNT;
+            final Block<?> targetBlock = world.getBlockType(tilePos);
+            final boolean isTNT = targetBlock == Blocks.TNT;
+
+            // Logs should always scorch when they burn, never convert into a fire block first.
+            if (targetBlock.getLogic() instanceof BlockLogicLog) {
+                this.setBurnResult(world, tilePos);
+                return;
+            }
 
             if (random.nextInt(meta + 10) < 5 && !world.isBlockBeingRainedOn(tilePos)) {
                 if (this.getBurnResult(world, tilePos) == Blocks.AIR /* Fix for fire destroying moss blocks */) {
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java
index be61c32b0..a2371a7ec 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicLog.java
@@ -1,10 +1,16 @@
 package net.minecraft.core.block;
 
+import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.material.Materials;
+import net.minecraft.core.enums.EnumDropCause;
+import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.item.ItemCoal;
+import net.minecraft.core.item.Items;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.pos.TilePos;
 import net.minecraft.core.world.pos.TilePosc;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class BlockLogicLog extends BlockLogicAxisAligned {
 
@@ -12,6 +18,17 @@ public class BlockLogicLog extends BlockLogicAxisAligned {
         super(block, Materials.WOOD);
     }
 
+    @Override
+    public @NotNull ItemStack @Nullable [] getBreakResult(@NotNull World world, @NotNull EnumDropCause dropCause, int data, @Nullable TileEntity tileEntity) {
+        if (this.block == Blocks.LOG_SCORCHED) {
+            return switch (dropCause) {
+                case PISTON_CRUSH -> new ItemStack[] { new ItemStack(Items.COAL, 1, ItemCoal.META_CHARCOAL) };
+                default -> new ItemStack[] { new ItemStack(this.block) };
+            };
+        }
+        return super.getBreakResult(world, dropCause, data, tileEntity);
+    }
+
     @Override
     public void onRemoved(@NotNull World world, @NotNull TilePosc tilePos, int data) {
         byte r = 4;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawner.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawner.java
index e2ffc3aff..6b3582219 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawner.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMobSpawner.java
@@ -2,6 +2,7 @@ package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.entity.TileEntityMobSpawner;
+import net.minecraft.core.block.material.Material;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
@@ -94,4 +95,9 @@ public class BlockLogicMobSpawner extends BlockLogicMobSpawnerDeactivated {
         }
         return null;
     }
+
+    @Override
+    public int getPistonPushReaction(@NotNull World world, @NotNull TilePosc tilePos) {
+        return Material.PISTON_CANT_PUSH;
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicObsidian.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicObsidian.java
new file mode 100644
index 000000000..4b99b63d3
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicObsidian.java
@@ -0,0 +1,19 @@
+package net.minecraft.core.block;
+
+import org.jetbrains.annotations.NotNull;
+
+import net.minecraft.core.block.material.Material;
+import net.minecraft.core.block.material.Materials;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.pos.TilePosc;
+
+public class BlockLogicObsidian extends BlockLogic {
+    public BlockLogicObsidian(@NotNull Block<?> block) {
+        super(block, Materials.STONE);
+    }
+
+    @Override
+    public int getPistonPushReaction(@NotNull World world, @NotNull TilePosc tilePos) {
+        return Material.PISTON_CANT_PUSH;
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java
index d65472331..de4c866ce 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.TileEntity;
+import net.minecraft.core.block.material.Material;
 import net.minecraft.core.block.material.Materials;
 import net.minecraft.core.block.support.ISupport;
 import net.minecraft.core.block.support.PartialSupport;
@@ -426,4 +427,9 @@ public class BlockLogicPortal extends BlockLogicTransparent implements IPainted
 
     public record Bounds(@NotNull Axis axis, @NotNull TilePos pos, int maxBoundA, int maxBoundB) {
     }
+
+    @Override
+    public int getPistonPushReaction(@NotNull World world, @NotNull TilePosc tilePos) {
+        return Material.PISTON_CANT_PUSH;
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicStatue.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStatue.java
index 687a4a1fb..3995f8013 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicStatue.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicStatue.java
@@ -56,7 +56,7 @@ public class BlockLogicStatue extends BlockLogic {
         // Sneaking overrides all - next pose
         if (player.isSneaking()) {
             statueEntity.nextPose();
-            world.playSoundEffect(player, SoundCategory.WORLD_SOUNDS, (double) tilePos.x() + 0.5D, (double) tilePos.y() + 0.5D, (double) tilePos.z() + 0.5D, "random.scrape", 0.7F, 0.2F + world.rand.nextFloat() * 0.4F);
+            world.playSoundEffect(player, SoundCategory.WORLD_SOUNDS, (double) tilePos.x() + 0.5D, (double) tilePos.y() + 0.5D, (double) tilePos.z() + 0.5D, "tile.scrape", 0.7F, 0.2F + world.rand.nextFloat() * 0.4F);
             return true;
         }
 
@@ -148,7 +148,7 @@ public class BlockLogicStatue extends BlockLogic {
 
         // All else fails - next pose
         statueEntity.nextPose();
-        world.playSoundEffect(player, SoundCategory.WORLD_SOUNDS, (double) tilePos.x() + 0.5D, (double) tilePos.y() + 0.5D, (double) tilePos.z() + 0.5D, "scrape", 1.0F, 0.15F + world.rand.nextFloat() * 0.7F);
+        world.playSoundEffect(player, SoundCategory.WORLD_SOUNDS, (double) tilePos.x() + 0.5D, (double) tilePos.y() + 0.5D, (double) tilePos.z() + 0.5D, "tile.scrape", 1.0F, 0.15F + world.rand.nextFloat() * 0.7F);
         return true;
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/Blocks.java b/game/core/src/main/java/net/minecraft/core/block/Blocks.java
index b196dfd0f..5bfa788ba 100644
--- a/game/core/src/main/java/net/minecraft/core/block/Blocks.java
+++ b/game/core/src/main/java/net/minecraft/core/block/Blocks.java
@@ -345,8 +345,8 @@ public final class Blocks {
         .withSound(BlockSounds.PERMAFROST).withDisabledNeighborNotifyOnMetadataChange().withLitInteriorSurface(true)
         .withTags(BlockTags.MINEABLE_BY_PICKAXE);
 
-    public static final @NotNull Block<?> OBSIDIAN = register("obsidian", "minecraft:block/obsidian", 180, (b) -> new BlockLogic(b, Materials.STONE))
-        .withSound(BlockSounds.STONE).withHardness(10F).withBlastResistance(2000F).withOverrideColor(MaterialColor.paintedBlack).withImmovableFlagSet()
+    public static final @NotNull Block<?> OBSIDIAN = register("obsidian", "minecraft:block/obsidian", 180, (b) -> new BlockLogicObsidian(b))
+        .withSound(BlockSounds.STONE).withHardness(10F).withBlastResistance(2000F).withOverrideColor(MaterialColor.paintedBlack)
         .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CHAINLINK_FENCES_CONNECT, BlockTags.PISTON_CRUSHING);
 
     public static final @NotNull Block<?> GLASS = register("glass", "minecraft:block/glass", 190, (b) -> new BlockLogicGlass(b, Materials.GLASS))
@@ -425,10 +425,10 @@ public final class Blocks {
         .withOverrideColor(MaterialColor.stone);
 
     public static final @NotNull Block<?> BEDROCK = register("bedrock", "minecraft:block/bedrock", 260, (b) -> new BlockLogicBedrock(b, Materials.STONE))
-        .withSound(BlockSounds.STONE).withSetUnbreakable().withBlastResistance(6000000F).withImmovableFlagSet()
+        .withSound(BlockSounds.STONE).withSetUnbreakable().withBlastResistance(6000000F)
         .withTags(BlockTags.PISTON_CRUSHING, BlockTags.CHAINLINK_FENCES_CONNECT, BlockTags.PREVENT_MOB_SPAWNS);
     public static final @NotNull Block<?> BONESHALE = register("boneshale", "minecraft:block/boneshale", 261, (b) -> new BlockLogicBoneShale(b, Materials.STONE))
-        .withSound(BlockSounds.STONE).withHardness(16F).withBlastResistance(6000000F).withImmovableFlagSet()
+        .withSound(BlockSounds.STONE).withHardness(16F).withBlastResistance(6000000F)
         .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.CHAINLINK_FENCES_CONNECT, BlockTags.NETHER_MOBS_SPAWN);
 
     public static final @NotNull Block<BlockLogicFluid> FLUID_WATER_FLOWING = register("fluid.water.flowing", "minecraft:block/fluid_water_flowing", 270, (BlockLogicSupplier<BlockLogicFluid>) b -> new BlockLogicFluidFlowing(b, Materials.WATER, new FluidWater(), Blocks.FLUID_WATER_STILL))
@@ -760,7 +760,7 @@ public final class Blocks {
     public static final @NotNull Block<?> BUTTON_STONE = register("button.stone", "minecraft:block/button_stone", 470, BlockLogicButton::new)
         .withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
         .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_PICKAXE, BlockTags.PREVENT_MOB_SPAWNS);
-    public static final @NotNull Block<?> BUTTON_PLANKS = register("button.planks", "minecraft:block/button_planks", 471, BlockLogicButtonPlanks::new)
+    public static final @NotNull Block<?> BUTTON_PLANKS_OAK = register("button.planks", "minecraft:block/button_planks", 471, BlockLogicButtonPlanksOak::new)
         .withSound(BlockSounds.WOOD).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
         .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.MINEABLE_BY_AXE, BlockTags.PREVENT_MOB_SPAWNS);
     public static final @NotNull Block<BlockLogicButtonPainted> BUTTON_PLANKS_PAINTED = register("button.planks.painted", "minecraft:block/button_planks_painted", 472, BlockLogicButtonPainted::new)
@@ -806,20 +806,20 @@ public final class Blocks {
     public static final @NotNull Block<BlockLogicPistonBase> PISTON_BASE = register("piston.base", "minecraft:block/piston_base", 520, (BlockLogicSupplier<BlockLogicPistonBase>)b -> 
         new BlockLogicPistonBase(
             b, PistonCommon.TYPE_NORMAL,
-            (byte)12, (byte)1, EnumDropCause.SILK_TOUCH, false, Double.NaN
+            12, 0, 1, EnumDropCause.SILK_TOUCH, Double.NaN
         ))
         .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange()
         .withTags(BlockTags.MINEABLE_BY_PICKAXE);
     public static final @NotNull Block<BlockLogicPistonBase> PISTON_BASE_STICKY = register("piston.base.sticky", "minecraft:block/piston_base_sticky", 521, (BlockLogicSupplier<BlockLogicPistonBase>)b -> 
         new BlockLogicPistonBase(
             b, PistonCommon.TYPE_STICKY,
-            (byte)12, (byte)1, EnumDropCause.SILK_TOUCH, true, Double.NaN
+            12, 12, 1, EnumDropCause.SILK_TOUCH, Double.NaN
         ))
         .withSound(BlockSounds.STONE).withDisabledNeighborNotifyOnMetadataChange()
         .withTags(BlockTags.MINEABLE_BY_PICKAXE);
 
     public static final @NotNull Block<BlockLogicPistonHead> PISTON_HEAD = register("piston.head", "minecraft:block/piston_head", 522, (BlockLogicSupplier<BlockLogicPistonHead>)(b) -> new BlockLogicPistonHead(b, 4/16d, 4/16d))
-        .withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats().withImmovableFlagSet()
+        .withSound(BlockSounds.WOOD).withDisabledNeighborNotifyOnMetadataChange().withDisabledStats()
         .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE);
 
     public static final @NotNull Block<BlockLogicPistonMoving> PISTON_MOVING = register("piston.moving", "minecraft:block/piston_moving", 523, BlockLogicPistonMoving::new)
@@ -829,7 +829,7 @@ public final class Blocks {
     public static final @NotNull Block<BlockLogicPistonBase> PISTON_BASE_STEEL = register("piston.base.steel", "minecraft:block/piston_base_steel", 524, (BlockLogicSupplier<BlockLogicPistonBase>)b -> 
         new BlockLogicPistonBase(
             b, PistonCommon.TYPE_STEEL,
-            (byte)24, (byte)1, EnumDropCause.PISTON_CRUSH, false, 2.0
+            24, 0, 1, EnumDropCause.PISTON_CRUSH, 2.0
         ))
         .withSound(BlockSounds.METAL)
         .withHardness(5F)
@@ -967,7 +967,7 @@ public final class Blocks {
         .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.SULFURIC_FIRE_OVERLAY_SOURCE);
 
     public static final @NotNull Block<?> MOBSPAWNER = register("mobspawner", "minecraft:block/mobspawner", 640, BlockLogicMobSpawner::new)
-        .withSound(BlockSounds.METAL).withHardness(5F).withImmovableFlagSet()
+        .withSound(BlockSounds.METAL).withHardness(5F)
         .withTags(BlockTags.MINEABLE_BY_PICKAXE)
         .withOverrideColor(MaterialColor.lapis);
     public static final @NotNull Block<?> MOBSPAWNER_DEACTIVATED = register("mobspawner.deactivated", "minecraft:block/mobspawner_deactivated", 641, BlockLogicMobSpawnerDeactivated::new)
diff --git a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java
index 0dc111172..18d335387 100644
--- a/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java
+++ b/game/core/src/main/java/net/minecraft/core/block/entity/TileEntityBasket.java
@@ -22,8 +22,6 @@ import org.jetbrains.annotations.NotNull;
 import org.joml.primitives.AABBd;
 import org.joml.primitives.AABBdc;
 
-import static net.minecraft.core.world.save.conversion.ItemConverters.legacyBucketConverter;
-
 public class TileEntityBasket extends TileEntity implements ICarrySource {
     private int numUnitsInside = 0;
     private final Object2IntMap<BasketEntry> contents = new Object2IntArrayMap<>();
@@ -170,7 +168,7 @@ public class TileEntityBasket extends TileEntity implements ICarrySource {
         if (shouldUpdate) updateNumUnits();
     }
 
-    private boolean importItemStack(final ItemStack stack) {
+    private boolean importItemStack(final @NotNull ItemStack stack) {
         BasketEntry entry = new BasketEntry(stack.itemID, stack.getMetadata(), stack.getData());
         final int sizeUnits = getItemSizeUnits(stack.getItem());
         final int freeUnits = getMaxUnits() - numUnitsInside;
@@ -239,53 +237,46 @@ public class TileEntityBasket extends TileEntity implements ICarrySource {
         return super.pickup(world, holder, tilePos_);
     }
 
-    private static final class BasketEntry {
-        public final int id;
-        public final int metadata;
-        public final CompoundTag tag;
-
-        public BasketEntry(final int id, final int metadata, final CompoundTag tag) {
-            this.id = id;
-            this.metadata = metadata;
-            this.tag = tag;
-        }
+    private record BasketEntry(int id, int metadata, CompoundTag tag) {
 
-        public static BasketEntry read(final CompoundTag tag) {
+        public static @NotNull BasketEntry read(final @NotNull CompoundTag tag) {
 
-            legacyBucketConverter(tag);
+                final int id = tag.getShort("id");
+                final int damage = tag.getShort("Damage");
+                final CompoundTag data = tag.getCompound("Data");
 
-            final int id = tag.getShort("id");
-            final int damage = tag.getShort("Damage");
-            final CompoundTag data = tag.getCompound("Data");
+                return new BasketEntry(id, damage, data);
+            }
 
-            return new BasketEntry(id, damage, data);
-        }
+            public static void write(final @NotNull CompoundTag tag, final @NotNull BasketEntry entry) {
+                tag.putShort("id", (short) entry.id);
+                tag.putShort("Damage", (short) entry.metadata);
+                tag.putCompound("Data", entry.tag);
+            }
 
-        public static void write(final CompoundTag tag, final BasketEntry entry) {
-            tag.putShort("id", (short) entry.id);
-            tag.putShort("Damage", (short) entry.metadata);
-            tag.putCompound("Data", entry.tag);
-        }
+            public Item getItem() {
+                return Item.itemsList[this.id];
+            }
 
-        public Item getItem() {
-            return Item.itemsList[this.id];
-        }
+            private boolean shouldCompareFullTag() {
+                return this.tag.containsKey("State") || this.tag.containsKey("Charges") || this.tag.getValues().size() > 2;
+            }
 
-        @Override
-        public boolean equals(final Object obj) {
-            if (!(obj instanceof BasketEntry)) return false;
-            final BasketEntry other = (BasketEntry) obj;
-            if (this.id != other.id || this.metadata != other.metadata) return false;
-            return this.tag.getValues().size() <= 2 && other.tag.getValues().size() <= 2;
-        }
+            @Override
+            public boolean equals(final Object obj) {
+                if (!(obj instanceof BasketEntry other)) return false;
+                if (this.id != other.id || this.metadata != other.metadata) return false;
+                if (this.shouldCompareFullTag() || other.shouldCompareFullTag()) {
+                    return this.tag.equals(other.tag);
+                }
+                return true;
+            }
 
-        @Override
-        public int hashCode() {
-            if (this.tag.getValues().size() <= 2) {
-                return Objects.hash(this.id, this.metadata);
-            } else {
-                return Objects.hash(this.id, this.metadata, this.tag);
+            @Override
+            public int hashCode() {
+                return this.shouldCompareFullTag()
+                    ? Objects.hash(this.id, this.metadata, this.tag)
+                    : Objects.hash(this.id, this.metadata);
             }
         }
-    }
 }
\ No newline at end of file
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 0bf60b445..0b818cb64 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
@@ -39,16 +39,15 @@ import static net.minecraft.core.block.piston.PistonCommon.*;
 public class BlockLogicPistonBase extends BlockLogic {
 	public final byte typeId;
 
-    final byte pushLimit, crushLimit;
+    final byte pushLimit, pullLimit, crushLimit;
     final @Nullable EnumDropCause crushAction;
-    final boolean canPull;
     final double flingStrength;
 
     public BlockLogicPistonBase(
         @NotNull Block<? extends BlockLogicPistonBase> block, 
         byte typeId,
-        byte pushLimit, byte crushLimit,
-        @Nullable EnumDropCause crushAction, boolean canPull, double flingStrength
+        int pushLimit, int pullLimit, int crushLimit,
+        @Nullable EnumDropCause crushAction, double flingStrength
     ) {
         super(block, Materials.PISTON);
         block.withHardness(0.5F);
@@ -57,10 +56,10 @@ public class BlockLogicPistonBase extends BlockLogic {
         assert typeId >= 0 && typeId < 3;
         assert pushLimit <= 64;
 
-        this.pushLimit = pushLimit;
-        this.crushLimit = crushLimit;
+        this.pushLimit = (byte)pushLimit;
+        this.pullLimit = (byte)pullLimit;
+        this.crushLimit = (byte)crushLimit;
         this.crushAction = crushAction;
-        this.canPull = canPull;
         this.flingStrength = flingStrength;
     }
 
@@ -77,15 +76,20 @@ public class BlockLogicPistonBase extends BlockLogic {
         final boolean powered = hasNeighborSignal(world, tilePos, Direction.fromId(DIRECTION.get(data)));
         final boolean extended = IS_EXTENDED.bool(data);
         final boolean detached = IS_DETACHED.bool(data);
+        final var dir = Direction.fromId(DIRECTION.get(data));
         
         if (powered == extended) return false;
 
         int event = (!detached) ? EVENT_EXTEND : EVENT_DETACH_EXTEND;
         event |= (powered) ? 0 : 1;
 
-        final var lineInfo = (powered && !detached)
-            ? testLine(world, tilePos, Direction.fromId(DIRECTION.get(data)))
-            : 0;
+        final int lineInfo;
+        if (detached) {
+            lineInfo = 0;
+        } else {
+            lineInfo = (powered) ? testPushLine(world, tilePos, dir) : testPullLine(world, tilePos, dir);
+        }
+
         assert (lineInfo & ~0xFF) == 0;
 
         if (LINE_OBSTRUCTED.bool(lineInfo)) return false;
@@ -121,7 +125,7 @@ public class BlockLogicPistonBase extends BlockLogic {
                     // serverside / singleplayer should have already fixed this 
                     fixLegacyBaseData(world, tilePos);
                 }
-                this.retract(world, tilePos, data);
+                this.retract(world, tilePos, data, eventData);
             }
             break;
         }
@@ -218,30 +222,46 @@ public class BlockLogicPistonBase extends BlockLogic {
      * if {@code LINE_OBSTRUCTED.bool(n)}, line can't be pushed; <br>
      * if {@code CRUSH_EOL.bool(n)}, end of line should be crushed; <br>
      */
-    public int testLine(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Direction dir) {
+    public int testPushLine(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Direction dir) {
         final var pos = new TilePos(tilePos).add(dir);
-        final int maxY = world.getHeightBlocks();
-        final int pushLimit = LINE_LENGTH.get(this.pushLimit);
-
-        if (pushLimit == 0) return 0;
-        for (int i = 0; i <= pushLimit; i++, pos.add(dir)) {
-            final int nope = LINE_OBSTRUCTED.mask | i;
+        final int limit = LINE_LENGTH.get(this.pushLimit);
 
-            if (pos.y < 0 || pos.y >= maxY) return nope;
-
-            switch (Movability.test(world, pos)) {
+        if (limit == 0) return 0;
+        for (int i = 0; i <= limit; i++, pos.add(dir)) {
+            switch (Movability.test(world, pos, dir)) {
             case BREAKS: 
                 return i;
-            case MOVES:
-                if (i >= pushLimit) return nope;
+            case PUSHES, PULLS:
+                if (i >= limit) return LINE_OBSTRUCTED.mask | i;
                 continue;
             case CRUSHES:
-                if (this.crushAction == null) return nope; 
-                if (i == 0) return nope;
-                if (i > this.crushLimit) return nope;
+                if (this.crushAction == null) return LINE_OBSTRUCTED.mask | i; 
+                if (i == 0) return LINE_OBSTRUCTED.mask | i;
+                if (i > this.crushLimit) return LINE_OBSTRUCTED.mask | i;
                 return CRUSH_EOL.mask | i - 1;
             case OBSTRUCTED:
-                return nope;
+                return LINE_OBSTRUCTED.mask | i;
+            }
+            assert false : "unreachable";
+        }
+        assert false : "unreachable"; return 0;
+    }
+
+    public int testPullLine(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Direction dir) {
+        final var pos =  new TilePos(tilePos).add(dir).add(dir);
+        final int limit = LINE_LENGTH.get(this.pullLimit);
+
+        if (limit == 0) return 0;
+        for (int i = 0; i <= limit; i++, pos.add(dir)) {
+            switch (Movability.test(world, pos, dir)) {
+            case PULLS:
+                if (i >= limit) return 0;
+                continue;
+            case PUSHES:
+                if (i >= limit) return 0;
+                return i + 1;
+            case BREAKS, CRUSHES, OBSTRUCTED:
+                return i;
             }
             assert false : "unreachable";
         }
@@ -249,18 +269,26 @@ public class BlockLogicPistonBase extends BlockLogic {
     }
 
     public static enum Movability {
-        OBSTRUCTED, MOVES, BREAKS, CRUSHES;
+        OBSTRUCTED, PUSHES, PULLS, BREAKS, CRUSHES;
 
-        public static @NotNull Movability test(@NotNull World world, @NotNull TilePosc tilePos) {
+        public static @NotNull Movability test(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Direction direction) {
+            if (tilePos.y() < 0 || tilePos.y() >= world.getHeightBlocks()) return OBSTRUCTED;
+            
             final var block = world.getBlockType(tilePos);
-            if (block == Blocks.AIR) return BREAKS;
             if (block.hasTag(BlockTags.PISTON_CRUSHING)) return CRUSHES;
-            switch (block.getPistonPushReaction(world, tilePos)) {
-                case Material.PISTON_DESTROY_ON_PUSH: return BREAKS;
-                case Material.PISTON_CANT_PUSH: return OBSTRUCTED;
-            }
-            if (block.getImmovable() || block.getHardness() == -1F) return OBSTRUCTED;
-            return MOVES;
+
+            return switch (block.getPistonPushReaction(world, tilePos)) {
+                case Material.PISTON_DESTROY_ON_PUSH -> BREAKS;
+                case Material.PISTON_CANT_PUSH -> OBSTRUCTED;
+                default -> {
+                    // hardcoded. I don't want premature abstraction until we do sticky blocks for real
+                    if (block != Blocks.PISTON_HEAD) yield PUSHES;
+                    final var data = world.getBlockData(tilePos);
+                    if (TYPE.get(data) != TYPE_STICKY) yield PUSHES;
+                    if (DIRECTION.get(data) != direction.id) yield PUSHES;
+                    yield PULLS;
+                }
+            };
         }
     }
 
@@ -276,13 +304,15 @@ public class BlockLogicPistonBase extends BlockLogic {
     //     └─ ?pull
     // 
 
-    private boolean extend(@NotNull World world, @NotNull TilePosc tilePos, int data, int lineInfo) {
+    private boolean extend(@NotNull World world, @NotNull TilePosc basePos, int data, int lineInfo) {
         data = validateBaseData(data, this);
         final var dir = Direction.fromId(DIRECTION.get(data));
-        final var headPos = new TilePos(tilePos).add(dir);
-
-        world.setBlockData(tilePos, IS_EXTENDED.set(data, 1));
-        world.markBlockNeedsUpdate(tilePos);
+        
+        final TilePos query1 = new TilePos(), query2 = new TilePos();
+        final TilePosc headPos = new TilePos(basePos).add(dir);
+        
+        world.setBlockData(basePos, IS_EXTENDED.set(data, 1));
+        world.markBlockNeedsUpdate(basePos);
 
         final boolean canFling = !Double.isNaN(this.flingStrength);
         if (canFling) flingEntity(world, headPos, dir);
@@ -291,13 +321,20 @@ public class BlockLogicPistonBase extends BlockLogic {
         final boolean shouldCrush = CRUSH_EOL.bool(lineInfo);
         final boolean shouldFling = !shouldCrush && canFling && len == 1;
 
-        @Nullable MovingLine line = null;
+        final @Nullable MovingLine line;
         if (shouldFling) {
-            flingBlock(world, headPos, dir);
+            this.flingBlock(world, headPos, dir);
+            line = null;
         } else {
             final var tailAction = (shouldCrush) ? this.crushAction : EnumDropCause.WORLD;
-            breakTail(tailAction, world, headPos, dir, len);
-            line = push(world, headPos, dir, len);
+            this.breakTail(tailAction, world, headPos, dir, len);
+            line = (len > 0) ? new MovingLine(len, world, dir, headPos, true) : null;
+        }
+
+        if (line != null) {
+            line.init(query1);
+            line.computeSignalMask();
+            line.move(query1);
         }
 
         final var headData = DIRECTION.set(0, dir.id) | TYPE.getNoShift(data);
@@ -308,64 +345,13 @@ public class BlockLogicPistonBase extends BlockLogic {
         world.setBlockTypeDataEntity(headPos, Blocks.PISTON_MOVING, headData, headMoving);
 
         // extension updates base immediately, and head 3 ticks after 
-        world.notifyBlocksOfNeighborChange(tilePos, this.block);
+        world.notifyBlocksOfNeighborChange(basePos, this.block);
 
-        if (line != null) {
-            final var tar = new TilePos();
-            final var src = new TilePos();
-
-            for (int i = len;  i > 0; ) {
-                i--;
-                line.getTargetPos(i, tar);
-                line.getSourcePos(i, src);
-                line.blocks[i].onMoved(world, src, tar, line.movingBlocks[i], i, line);
-            }
-        }
+        if (line != null) line.notify(query1, query2);
 
         return true;
     }
 
-    private static @Nullable MovingLine push(@NotNull World world, @NotNull TilePosc headPos, @NotNull Direction dir, int len) {
-        if (len <= 0) return null;
-        final TilePos pos1 = new TilePos(), pos2 = new TilePos();
-
-        final var line = new MovingLine(len, world, dir, headPos, true);
-
-        /* block type,data,entity lookup */ {
-            final var queryPos = pos1.set(headPos);
-            for (int i = 0;  i < len;  i++, queryPos.add(dir)) {
-                line.blocks[i] = world.getBlockType(queryPos);
-                line.data[i] = (byte)world.getBlockData(queryPos);
-                line.entities[i] = world.getTileEntity(queryPos);
-
-                // We DON'T handle moving piston, as it is ruled out in movability test
-                assert line.blocks[i] != Blocks.PISTON_MOVING;
-                assert !(line.entities[i] instanceof TileEntityMovingPistonBlock);
-            }
-        }
-
-        line.computeConductMask();
-        line.computeSignalMask();
-        
-        /* move */ {
-            final var tar = dir.offsetScaled(pos1.set(headPos), len);
-            final var src = dir.offsetScaled(pos2.set(headPos), len - 1);
-
-            for (int i = len;  i > 0;  src.sub(dir), tar.sub(dir)) {
-                i--;
-                assert tar != headPos;
-
-                world.removeTileEntity(src);
-                world.setBlockTypeRaw(src, Blocks.AIR);
-
-                world.setBlockTypeDataEntity(tar, Blocks.PISTON_MOVING, line.data[i], line.createMoving(i));
-            }
-        }
-
-        return line;
-    }
-
-
     private void breakTail(
         @NotNull EnumDropCause cause, @NotNull World world, @NotNull TilePosc headPos,
         @NotNull Direction dir, int off
@@ -373,7 +359,7 @@ public class BlockLogicPistonBase extends BlockLogic {
         final var target = dir.offsetScaled(new TilePos(headPos), off);
 
         final var block = world.getBlockType(target);
-        if (block.id() > 0) {
+        if (block != Blocks.AIR) {
             world.playBlockEvent(null, target, LevelListener.EVENT_BLOCK_BREAK, block.id());
         }
 
@@ -391,6 +377,7 @@ public class BlockLogicPistonBase extends BlockLogic {
         // note that flingEntity is performed before flingBlock, therefore no need to 
         // check for flingBlock
         for (final var entity : entities) {
+            if (entity.noPhysics) continue;
             entity.fling(vx, vy, vz, 1f);
         }
     }
@@ -426,10 +413,16 @@ public class BlockLogicPistonBase extends BlockLogic {
         block.onFlung(world, headPos, blockMeta, flungBlock.carriedBlock);
     }
 
-    private void retract(@NotNull World world, @NotNull TilePosc tilePos, int data) {
+    private void retract(@NotNull World world, @NotNull TilePosc basePos, int data, int lineInfo) {
         data = validateBaseData(data, this);
         final var dir = Direction.fromId(DIRECTION.get(data));
-        final var headPos = new TilePos(tilePos).add(dir);
+
+        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 int len = LINE_LENGTH.get(lineInfo);
 
         if (world.getTileEntity(headPos) instanceof TileEntityMovingPistonBlock moving && !moving.isExtending) {
             moving.finalTick();
@@ -440,55 +433,23 @@ public class BlockLogicPistonBase extends BlockLogic {
         final var moving = new TileEntityMovingPistonBlock(
             MovingType.RETRACTING_PISTON,
             this.block, dir.id, null, dir);
-        world.setBlockTypeRaw(tilePos, Blocks.AIR);
-        world.setBlockTypeDataEntity(tilePos, Blocks.PISTON_MOVING, data, moving);
-
-        if (this.canPull) pull(world, headPos, dir);
+        world.setBlockTypeRaw(basePos, Blocks.AIR);
+        world.setBlockTypeDataEntity(basePos, Blocks.PISTON_MOVING, data, moving);
+
+        if (len > 0) {
+            final var line = new MovingLine(len, world, dir, sourcePos, false);
+            line.init(query1);
+            line.computeSignalMask();
+            line.move(query1);
+            line.notify(query1, query2);
+        }
 
         // logically, retraction should only update head immediately, and base 3 ticks after
         // but this emulates the old behavior
-        world.notifyBlocksOfNeighborChange(tilePos, this.block);
+        world.notifyBlocksOfNeighborChange(basePos, this.block);
         world.notifyBlocksOfNeighborChange(headPos, null);
     }
 
-    private static void pull(@NotNull World world, @NotNull TilePosc headPos, @NotNull Direction dir) {
-        final var tar = headPos;
-        final var src = new TilePos(tar).add(dir);
-
-        final var entity = world.getTileEntity(src);
-
-        if (entity instanceof TileEntityMovingPistonBlock moving) position_moving: {
-            if (moving.direction != dir) break position_moving;
-            if (!moving.isExtending) break position_moving;
-            assert world.getBlockType(src) == Blocks.PISTON_MOVING;
-
-            // 0t
-            moving.finalTick();
-            return;
-        }
-
-        if (Movability.test(world, src) != Movability.MOVES) {
-            world.removeTileEntity(tar);
-            world.setBlockType(tar, Blocks.AIR);
-            return;
-        }
-
-        final var block = world.getBlockType(src);
-        final var data = world.getBlockData(src);
-        world.removeTileEntity(src);
-
-        final var line = new MovingLine(1, world, dir, headPos, false);
-        line.blocks[0] = block;
-        line.data[0] = (byte)data;
-        line.entities[0] = entity;
-
-        world.setBlockTypeRaw(src, Blocks.AIR);
-        world.setBlockTypeDataEntity(tar, Blocks.PISTON_MOVING, data, line.createMoving(0));
-
-        block.onMoved(world, src, tar, line.movingBlocks[0], 0, line);
-        world.notifyBlocksOfNeighborChange(src, Blocks.AIR);
-    }
-
     // BlockLogic impl:
     // ====================
 
@@ -633,4 +594,16 @@ public class BlockLogicPistonBase extends BlockLogic {
         ctx.buf[0] = new ItemStack(this.block, 1, data);
         return ctx.buf;
     }
+
+    @Override
+    public @NotNull String getLanguageKey(int data) {
+        interface ctx {
+            String[] KEYMAP = {
+                BASE_BLOCK_MAP[TYPE_NORMAL].getKey() + ".detached",
+                BASE_BLOCK_MAP[TYPE_STICKY].getKey() + ".detached",
+                BASE_BLOCK_MAP[TYPE_STEEL].getKey() + ".detached",
+            }; 
+        }
+        return (IS_DETACHED.bool(data)) ? ctx.KEYMAP[this.typeId] : this.block.getKey();
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java
index 4a3d1de91..e8f2f9aba 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonMoving.java
@@ -22,6 +22,7 @@ import java.util.List;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.joml.primitives.AABBd;
 import org.joml.primitives.AABBdc;
 
 public class BlockLogicPistonMoving extends BlockLogic {
@@ -110,32 +111,26 @@ public class BlockLogicPistonMoving extends BlockLogic {
         @NotNull World world, @NotNull TilePosc tilePos,
         @NotNull AABBdc aabb, @NotNull List<@NotNull AABBdc> aabbList
     ) {
-        aabbList.add(this.getCollisionAABB(world, tilePos));
-
         if (!(world.getTileEntity(tilePos) instanceof TileEntityMovingPistonBlock moving)) return;
 
+        for (final var collision : moving.collisions) {
+            super.addIntersectingBoundingBox(aabb, collision, aabbList);
+        }
+        
         final boolean isRetractingPiston = !moving.isExtending && moving.isSourcePiston;
         if (!isRetractingPiston || !(moving.movingBlock.getLogic() instanceof BlockLogicPistonBase base)) return;
 
-        final var thickness = HEAD_BLOCK_MAP[base.typeId].getLogic().headThickness;        
-        aabbList.add(getBaseCollision(moving.direction, thickness).translate(tilePos.x(), tilePos.y(), tilePos.z()));
-        return;
-    }
-
-    @Override
-    public @Nullable AABBdc getCollisionAABB(@NotNull WorldSource source, @NotNull TilePosc tilePos) {
-        if (!(source.getTileEntity(tilePos) instanceof TileEntityMovingPistonBlock moving)) {
-            return null;
-        }
-        return moving.collision;
+        final var thickness = HEAD_BLOCK_MAP[base.typeId].getLogic().headThickness;
+        final var baseCollision = getBaseCollision(moving.direction, thickness).translate(tilePos.x(), tilePos.y(), tilePos.z());
+        super.addIntersectingBoundingBox(aabb, baseCollision, aabbList);
+        super.addIntersectingBoundingBox(aabb, new AABBd(0,0,0, 1,1,1).translate(tilePos.x(), tilePos.y(), tilePos.z()), aabbList);
     }
 
     @Override
     public @NotNull AABBdc getBoundsFromState(@NotNull WorldSource source, @NotNull TilePosc tilePos) {
-        if (source.getTileEntity(tilePos) instanceof TileEntityMovingPistonBlock piston) {
-            return piston.bounds;
-        }
-        return super.getBoundsFromState(source, tilePos);
+        return (source.getTileEntity(tilePos) instanceof TileEntityMovingPistonBlock piston)
+            ? piston.bounds
+            : super.getBoundsFromState(source, tilePos);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/MovingLine.java b/game/core/src/main/java/net/minecraft/core/block/piston/MovingLine.java
index 53312fb3c..fdb808614 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/MovingLine.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/MovingLine.java
@@ -94,21 +94,43 @@ public final class MovingLine {
         }
     }
 
-    long computeConductMask() {
-        final var queryPos = new TilePos();
-        long set;
+    void init(@NotNull TilePos query) {
+        query.set(this.origin);
+        for (int i = 0;  i < this.len;  i++, query.add(this.direction)) {
+            this.blocks[i] = world.getBlockType(query);
+            this.data[i] = (byte)world.getBlockData(query);
+            this.entities[i] = world.getTileEntity(query);
+
+            assert this.blocks[i] != Blocks.PISTON_MOVING;
+            assert !(this.entities[i] instanceof TileEntityMovingPistonBlock);
+        }
+    }
 
-        set = 0b1L;
-        queryPos.set(this.origin);
-        for (int i = 0;  i < this.len;  i++, set <<= 1, queryPos.add(this.direction)) {
-            if (!world.isBlockNormalCube(queryPos)) continue;
-            if (this.blocks[i] == Blocks.BLOCK_REDSTONE) continue;
-            if (this.blocks[i] == Blocks.PUMPKIN_REDSTONE) continue;
-            if (this.blocks[i] == Blocks.MATCHER_ACTIVE) continue;
-            this.conductMask |= set;
+    void move(@NotNull TilePos query) {
+        query.set(this.origin);
+        for (int i = 0; i < len; i++, query.add(this.direction)) {
+            world.removeTileEntity(query);
+            world.setBlockTypeRaw(query, Blocks.AIR);
+            world.markBlockDirty(query);
         }
+        if (this.isExtending) world.markBlockDirty(query.add(this.direction));
 
-        return this.conductMask;
+        query.set(this.origin).add(this.movingDirection());
+        if (!this.isExtending) world.markBlockDirty(query);
+
+        for (int i = 0; i < len; i++, query.add(this.direction)) {
+            world.setBlockTypeDataEntity(query, Blocks.PISTON_MOVING, this.data[i], this.createMoving(i));
+        }
+    }
+
+    void notify(@NotNull TilePos query1, @NotNull TilePos query2) {
+        final var src = query1.set(this.origin);
+        final var tar = query2.set(this.origin).sub(this.direction);
+
+        for (int i = 0;  i < len;  src.add(this.direction), tar.add(this.direction)) {
+            this.blocks[i].onMoved(world, src, tar, this.movingBlocks[i], i, this);
+            i++;
+        }
     }
 
     // TODO: this can be far more efficient, but the pumpkin edgecase sucks
diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/PistonCommon.java b/game/core/src/main/java/net/minecraft/core/block/piston/PistonCommon.java
index 7c628eb80..51bd8ecf2 100644
--- a/game/core/src/main/java/net/minecraft/core/block/piston/PistonCommon.java
+++ b/game/core/src/main/java/net/minecraft/core/block/piston/PistonCommon.java
@@ -47,7 +47,8 @@ public abstract class PistonCommon {
 
     /**
      * Event data encodes line length.
-     * @see BlockLogicPistonBase#testLine(World, TilePosc, int)
+     * @see BlockLogicPistonBase#testPushLine(World, TilePosc, int)
+     * @see BlockLogicPistonBase#testPullLine(World, TilePosc, int)
      */ 
     public static final byte EVENT_EXTEND         = 0b00_0; 
     public static final byte EVENT_RETRACT        = 0b00_1;
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 63b7c6496..0dfc65837 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
@@ -45,6 +45,18 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
     final @NotNull AABBd sweptCollision = new AABBd();
     final @NotNull Vector3d directionScaled = new Vector3d();
 
+    static final @NotNull Vector3d[] SCALED_DIR_MAP = new Vector3d[6];
+    static {
+        for (final var dir : Direction.all) {
+            SCALED_DIR_MAP[dir.id] = dir.getOffsetScaled(new Vector3d(), PROGRESS_DELTA);
+        }
+    }
+
+    @NotNull AABBd @NotNull[] collisions; {
+        interface ctx { static AABBd[] EMPTY = {}; }
+        collisions = ctx.EMPTY;
+    }
+
     // awkward
     // TODO provide an actual initiallization event that is guaranteed to be called after
     // TODO   tile entity is valid (i.e. not .validate())
@@ -81,8 +93,6 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
         this.direction = direction;
         this.isExtending = type.isExtending;
         this.isSourcePiston = type.isSourcePiston;
-
-        this.movingDirection().getOffsetScaled(this.directionScaled, PROGRESS_DELTA);
     }
 
     @Override
@@ -99,18 +109,25 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
         assert this.worldObj != null;
         assert this.worldObj.isChunkLoaded(new ChunkPos(this.tilePos));
 
-        final var dir = this.movingDirection();
+        interface ctx {
+            Vector3d offset = new Vector3d();
+            ArrayList<AABBdc> collisions = new ArrayList<>(2);
+            AABBdc hugeBB = new AABBd(new Vector3d(Double.NEGATIVE_INFINITY), new Vector3d(Double.POSITIVE_INFINITY));
+        }
 
-        final var off = dir.opposite().getOffset(new Vector3d());
-        this.bounds
-            .set(this.movingBlock.getBoundsFromState(this.worldObj, this.tilePos))
-            .translate(off);
+        this.movingDirection().opposite().getOffset(ctx.offset);
+        this.bounds.set(this.movingBlock.getBoundsFromState(this.worldObj, this.tilePos)).translate(ctx.offset);
 
-        var collision = this.movingBlock.getCollisionAABB(this.worldObj, this.tilePos);
-        if (collision == null) collision = new AABBd(0,0,0,0,0,0);
-        this.collision
-            .set(collision)
-            .translate(off);
+        final var collision = this.movingBlock.getCollisionAABB(this.worldObj, this.tilePos);
+        if (collision != null) this.collision.set(collision).translate(ctx.offset);
+        else this.collision.set(this.bounds).translate(this.tilePos.x(), this.tilePos.y(), this.tilePos.z());
+
+        this.movingBlock.getCollisionAABBs(worldObj, this.tilePos, ctx.hugeBB, ctx.collisions);
+        this.collisions = new AABBd[ctx.collisions.size()];
+        for (int i = 0; i < ctx.collisions.size(); i++) {
+            this.collisions[i] = ctx.collisions.get(i).translate(ctx.offset, new AABBd());
+        }
+        ctx.collisions.clear();
 
         this.isCollisionInited = true;
     }
@@ -123,19 +140,21 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
         if (this.lifetime ++ >= TICKS_TO_EXTEND) {
             this.finalTick();
         } else {
+            final var dir = SCALED_DIR_MAP[this.movingDirection().id];
             this.sweptCollision.set(this.collision);
-            this.sweptCollision.translate(this.directionScaled);
+            this.sweptCollision.translate(dir);
             this.sweptCollision.union(this.collision);
 
             final var entities = this.worldObj.getEntitiesWithinAABBExcludingEntity(null, this.sweptCollision);
             for (final var e : entities) {
                 if (e.noPhysics) continue;
-                e.move(this.directionScaled.x, this.directionScaled.y, this.directionScaled.z);
+                e.move(dir.x, dir.y, dir.z);
             }
 
             // translate block collision after entities are moved
-            this.collision.translate(this.directionScaled);
-            this.bounds.translate(this.directionScaled);
+            this.bounds.translate(dir);
+            this.collision.translate(dir);
+            for (final var collision : this.collisions) collision.translate(dir);
         }
     }
 
@@ -184,10 +203,6 @@ public class TileEntityMovingPistonBlock extends TileEntity implements IMovingBl
 
         this.movingBlock.onMoveComplete(worldObj, selfPos);
 
-        // Block.disableNormalEntityLogic = true;
-        // this.movingBlock.onPlacedByWorld(this.worldObj, selfPos);
-        // Block.disableNormalEntityLogic = false;
-
         assert this.movingTileEntity == null || this.worldObj.getTileEntity(selfPos) == this.movingTileEntity 
             : "Piston failed to actually move entity!";
 
diff --git a/game/core/src/main/java/net/minecraft/core/data/registry/Registries.java b/game/core/src/main/java/net/minecraft/core/data/registry/Registries.java
index 1ec5676fe..1a2e889c2 100644
--- a/game/core/src/main/java/net/minecraft/core/data/registry/Registries.java
+++ b/game/core/src/main/java/net/minecraft/core/data/registry/Registries.java
@@ -122,7 +122,7 @@ public class Registries extends Registry<Registry<?>> {
             fencesStackList.add(Blocks.FENCE_PLANKS_OAK.getDefaultStack());
             fenceGatesStackList.add(Blocks.FENCE_GATE_PLANKS_OAK.getDefaultStack());
             trapdoorStackList.add(Blocks.TRAPDOOR_PLANKS_OAK.getDefaultStack());
-            woodenButtonsList.add(Blocks.BUTTON_PLANKS.getDefaultStack());
+            woodenButtonsList.add(Blocks.BUTTON_PLANKS_OAK.getDefaultStack());
             woodenPressurePlatesList.add(Blocks.PRESSURE_PLATE_PLANKS_OAK.getDefaultStack());
             buttonsList.add(Blocks.BUTTON_STONE.getDefaultStack());
             buttonsList.add(Blocks.BUTTON_BASALT.getDefaultStack());
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
index c62b4cf45..515df1f98 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
@@ -39,7 +39,7 @@ public class MobGhast extends MobFlying implements Enemy {
         setSize(4F, 4.5F);
         this.fireImmune = true;
         this.scoreValue = 1000;
-        this.mobDrops.add(new WeightedRandomLootObject(Items.GUNPOWDER.getDefaultStack(), 0, 2));
+        this.mobDrops.add(new WeightedRandomLootObject(Items.GUNPOWDER.getDefaultStack(), 3, 8));
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
index 597d3a3df..00c23627a 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
@@ -1152,6 +1152,7 @@ public abstract class Player
             hurt(null, 4, DamageType.FIRE);
             this.remainingFireTicks = (int) (80 + 520 * protection);
             this.maxFireTicks = this.remainingFireTicks;
+            this.activeFireBlock = Blocks.FIRE;
         }
     }
 
@@ -1162,6 +1163,7 @@ public abstract class Player
             hurt(null, 1, DamageType.FIRE);
             this.remainingFireTicks = (int) (40 + 260 * protection);
             this.maxFireTicks = this.remainingFireTicks;
+            this.activeFireBlock = Blocks.FIRE;
         }
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemSlimeball.java b/game/core/src/main/java/net/minecraft/core/item/ItemSlimeball.java
index e95545d96..df33c3039 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemSlimeball.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemSlimeball.java
@@ -62,9 +62,6 @@ public class ItemSlimeball extends Item {
         final TilePos bpos = new TilePos();
         int bdat = PistonCommon.headGetBase(data, bpos, world, blockPos);
         
-        System.err.println(bpos);
-        System.err.println(Integer.toBinaryString(bdat));
-
         final boolean isExtendedButNotDetached  = 
             PistonCommon.IS_DETACHED_OR_EXTENDED.get(bdat) == PistonCommon.IS_EXTENDED.mask;
         if (!isExtendedButNotDetached) {
diff --git a/game/core/src/main/java/net/minecraft/core/item/ItemStack.java b/game/core/src/main/java/net/minecraft/core/item/ItemStack.java
index acd647ec6..25f9f74e9 100644
--- a/game/core/src/main/java/net/minecraft/core/item/ItemStack.java
+++ b/game/core/src/main/java/net/minecraft/core/item/ItemStack.java
@@ -20,9 +20,6 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Objects;
 
-import static net.minecraft.core.world.save.conversion.ItemConverters.legacyBucketConverter;
-
-
 public final class ItemStack {
     public int stackSize;
     public int animationsToGo;
@@ -408,8 +405,6 @@ public final class ItemStack {
             return null;
         }
 
-        legacyBucketConverter(nbt);
-
         ItemStack stack = new ItemStack();
         stack.readFromNBT(nbt);
         if(stack.stackSize <= 0) {
diff --git a/game/core/src/main/java/net/minecraft/core/item/Items.java b/game/core/src/main/java/net/minecraft/core/item/Items.java
index d99e64d24..8af4c85fd 100644
--- a/game/core/src/main/java/net/minecraft/core/item/Items.java
+++ b/game/core/src/main/java/net/minecraft/core/item/Items.java
@@ -266,7 +266,7 @@ public final class Items {
         TOOL_SHOVEL_IRON = (new ItemToolShovel("tool.shovel.iron", "minecraft:item/tool_shovel_iron", 16384, ToolMaterial.iron));
         TOOL_PICKAXE_IRON = (new ItemToolPickaxe("tool.pickaxe.iron", "minecraft:item/tool_pickaxe_iron", 16385, ToolMaterial.iron));
         TOOL_AXE_IRON = (new ItemToolAxe("tool.axe.iron", "minecraft:item/tool_axe_iron", 16386, ToolMaterial.iron));
-        TOOL_FIRESTRIKER_IRON = (new ItemFireStriker("tool.firestriker", "minecraft:item/tool_firestriker_iron", 16387));
+        TOOL_FIRESTRIKER_IRON = (new ItemFireStriker("tool.firestriker.iron", "minecraft:item/tool_firestriker_iron", 16387));
         FOOD_APPLE = (new ItemFood("food.apple", "minecraft:item/food_apple", 16388, 4, 8, false, 8));
         TOOL_BOW = (new ItemBow("tool.bow", "minecraft:item/tool_bow", 16389));
         AMMO_ARROW = (new Item("ammo.arrow", "minecraft:item/ammo_arrow", 16390));
@@ -453,7 +453,7 @@ public final class Items {
         DOUGH = (new Item("dough", "minecraft:item/dough", 16552));
         WAND_NBT = new ItemWandNBT("wand.nbt", "minecraft:item/wand_nbt", 16553);
 
-        RUBYGLASS = (new Item("rubyglass", "minecraft:item/rubyglass_crystal", 16555));
+        RUBYGLASS = (new Item("rubyglass.crystal", "minecraft:item/rubyglass_crystal", 16555));
 
 
         ARMOR_WOLF_LEATHER = new ItemArmor<>("armor.wolf.leather", "minecraft:item/armor_wolf_leather", 16556, ArmorMaterial.LEATHER, WolfArmorShape.BODY);
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java
index f791eb4d1..02ec02e26 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockLadder.java
@@ -34,6 +34,7 @@ public class ItemBlockLadder<T extends BlockLogicLadder> extends ItemBlock<T> {
                 bp.down();
             }
         }
+        if (!world.canBlockIdBePlacedAt(this.block.id(), bp, false, side)) return false;
         final var meta = ladder.getMetaForSide(pside);
         if (!ladder.canExistAt(world, bp, meta)) return false;
         return super.placeDirectly(selfStack, world, player, bp, meta, pside, xHit, yHit);
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java
index 8544fd687..6075de3e5 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlockSlab.java
@@ -39,14 +39,14 @@ public class ItemBlockSlab<T extends BlockLogic> extends ItemBlock<T> {
         for (i = 0; i < 2; i++) {
             block = world.getBlockType(shiftPos);
             final var blockMeta = world.getBlockData(shiftPos);
-            final boolean canPlaceInto = 
+            final boolean canPlaceInto =
                 block == this.block &&
-                (blockMeta & ~0b11) == selfMeta &&
-                switch (blockMeta & 0b11) {
-                    default -> false;
-                    case 0 -> yHit >= 0.5f;
-                    case 2 -> yHit <= 0.5f;
-                };
+                    (blockMeta & ~0b11) == selfMeta &&
+                    switch (blockMeta & 0b11) {
+                        default -> false;
+                        case 0 -> yHit >= 0.5f;
+                        case 2 -> yHit <= 0.5f;
+                    };
             if (canPlaceInto) break;
             shiftPos.add(side);
             yHit -= side.offsetY();
@@ -62,7 +62,7 @@ public class ItemBlockSlab<T extends BlockLogic> extends ItemBlock<T> {
         selfStack.consumeItem(player);
 
         // this invokes modelBlock's on place logic. is this a good idea?
-        this.block.onPlacedByWorld(world, shiftPos); 
+        this.block.onPlacedByWorld(world, shiftPos);
 
         world.notifyBlockChange(shiftPos, block);
         world.playBlockSoundEffect(player,
@@ -71,4 +71,4 @@ public class ItemBlockSlab<T extends BlockLogic> extends ItemBlock<T> {
         
         return true;
     }
-}
+}
\ No newline at end of file
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeBlocks.java b/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeBlocks.java
deleted file mode 100644
index 5056f4e21..000000000
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeBlocks.java
+++ /dev/null
@@ -1,613 +0,0 @@
-package net.minecraft.core.player.inventory;
-
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
-import net.minecraft.core.block.IPainted;
-import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.util.helper.DyeColor;
-
-import java.util.List;
-
-public final class CreativeBlocks {
-
-	private static final DyeColor[] RAINBOW_ORDER = {
-		DyeColor.RED,
-		DyeColor.ORANGE,
-		DyeColor.YELLOW,
-		DyeColor.LIME,
-		DyeColor.GREEN,
-		DyeColor.CYAN,
-		DyeColor.LIGHT_BLUE,
-		DyeColor.BLUE,
-		DyeColor.PURPLE,
-		DyeColor.MAGENTA,
-		DyeColor.PINK,
-		DyeColor.BROWN,
-		DyeColor.WHITE,
-		DyeColor.SILVER,
-		DyeColor.GRAY,
-		DyeColor.BLACK
-	};
-
-	public static void populate(List<ItemStack> list) {
-
-		addStoneTypes(list);
-
-		addWoodTypes(list);
-
-		//WOOL
-		addPainted(list, Blocks.WOOL, painted(Blocks.WOOL));
-
-		addNaturalTypes(list);
-
-		addOrganicTypes(list);
-
-
-		//WORKSTATIONS
-		add(list, Blocks.WORKBENCH);
-
-		add(list, Blocks.FURNACE_STONE_IDLE);
-		add(list, Blocks.FURNACE_BLAST_IDLE);
-
-		add(list, Blocks.TROMMEL_IDLE);
-
-		add(list, Blocks.CHEST_PLANKS_OAK);
-		addPainted(list, Blocks.CHEST_PLANKS_OAK_PAINTED, painted(Blocks.CHEST_PLANKS_OAK_PAINTED));
-
-		add(list, Blocks.BOOKSHELF_PLANKS_OAK);
-		add(list, Blocks.LADDER_OAK);
-		add(list, Blocks.TORCH_COAL);
-
-		add(list, Blocks.GLASS);
-		add(list, Blocks.TRAPDOOR_GLASS);
-
-		add(list, Blocks.GLASS_TINTED);
-
-		add(list, Blocks.GLASS_STEEL);
-
-
-		addRedstoneTypes(list);
-
-		addOreTypes(list);
-
-		addStorageTypes(list);
-
-		add(list, Blocks.PAPER_WALL);
-		add(list, Blocks.FENCE_PAPER_WALL);
-
-		add(list, Blocks.FENCE_CHAINLINK);
-		add(list, Blocks.FENCE_STEEL);
-
-	}
-
-	public static void addStoneTypes(List<ItemStack> list) {
-		// STONE
-		add(list, Blocks.STONE);
-		add(list, Blocks.MOSS_STONE);
-
-		add(list, Blocks.COBBLE_STONE);
-		add(list, Blocks.STAIRS_COBBLE_STONE);
-		add(list, Blocks.SLAB_COBBLE_STONE);
-		add(list, Blocks.COBBLE_STONE_MOSSY);
-
-		add(list, Blocks.BRICK_STONE);
-		add(list, Blocks.STAIRS_BRICK_STONE);
-		add(list, Blocks.SLAB_BRICK_STONE);
-
-		add(list, Blocks.STONE_POLISHED);
-		add(list, Blocks.SLAB_STONE_POLISHED);
-		add(list, Blocks.STONE_CARVED);
-
-		add(list, Blocks.BRICK_STONE_POLISHED);
-		add(list, Blocks.STAIRS_BRICK_STONE_POLISHED);
-		add(list, Blocks.SLAB_BRICK_STONE_POLISHED);
-		add(list, Blocks.BRICK_STONE_POLISHED_MOSSY);
-
-
-		//BASALT
-		add(list, Blocks.BASALT);
-		add(list, Blocks.MOSS_BASALT);
-
-		add(list, Blocks.COBBLE_BASALT);
-		add(list, Blocks.STAIRS_COBBLE_BASALT);
-		add(list, Blocks.SLAB_COBBLE_BASALT);
-		add(list, Blocks.COBBLE_BASALT_MOSSY);
-
-		add(list, Blocks.BRICK_BASALT);
-		add(list, Blocks.STAIRS_BRICK_BASALT);
-		add(list, Blocks.SLAB_BRICK_BASALT);
-
-		add(list, Blocks.BASALT_POLISHED);
-		add(list, Blocks.SLAB_BASALT_POLISHED);
-		add(list, Blocks.BASALT_CARVED);
-
-
-		//LIMESTONE
-		add(list, Blocks.LIMESTONE);
-		add(list, Blocks.MOSS_LIMESTONE);
-
-		add(list, Blocks.COBBLE_LIMESTONE);
-		add(list, Blocks.STAIRS_COBBLE_LIMESTONE);
-		add(list, Blocks.SLAB_COBBLE_LIMESTONE);
-		add(list, Blocks.COBBLE_LIMESTONE_MOSSY);
-
-		add(list, Blocks.BRICK_LIMESTONE);
-		add(list, Blocks.STAIRS_BRICK_LIMESTONE);
-		add(list, Blocks.SLAB_BRICK_LIMESTONE);
-
-		add(list, Blocks.LIMESTONE_POLISHED);
-		add(list, Blocks.SLAB_LIMESTONE_POLISHED);
-		add(list, Blocks.LIMESTONE_CARVED);
-
-
-		//GRANITE
-		add(list, Blocks.GRANITE);
-		add(list, Blocks.MOSS_GRANITE);
-
-		add(list, Blocks.COBBLE_GRANITE);
-		add(list, Blocks.STAIRS_COBBLE_GRANITE);
-		add(list, Blocks.SLAB_COBBLE_GRANITE);
-		add(list, Blocks.COBBLE_GRANITE_MOSSY);
-
-		add(list, Blocks.BRICK_GRANITE);
-		add(list, Blocks.STAIRS_BRICK_GRANITE);
-		add(list, Blocks.SLAB_BRICK_GRANITE);
-
-		add(list, Blocks.GRANITE_POLISHED);
-		add(list, Blocks.SLAB_GRANITE_POLISHED);
-		add(list, Blocks.GRANITE_CARVED);
-
-
-		//PERMAFROST
-		add(list, Blocks.PERMAFROST);
-
-		add(list, Blocks.COBBLE_PERMAFROST);
-		add(list, Blocks.STAIRS_COBBLE_PERMAFROST);
-		add(list, Blocks.SLAB_COBBLE_PERMAFROST);
-
-		add(list, Blocks.BRICK_PERMAFROST);
-		add(list, Blocks.STAIRS_BRICK_PERMAFROST);
-		add(list, Blocks.SLAB_BRICK_PERMAFROST);
-
-		add(list, Blocks.PERMAFROST_POLISHED);
-		add(list, Blocks.SLAB_PERMAFROST_POLISHED);
-		add(list, Blocks.PERMAFROST_CARVED);
-
-
-		//NETHERRACK
-		add(list, Blocks.NETHERRACK);
-
-		add(list, Blocks.COBBLE_NETHERRACK);
-		add(list, Blocks.STAIRS_COBBLE_NETHERRACK);
-		add(list, Blocks.SLAB_COBBLE_NETHERRACK);
-		add(list, Blocks.COBBLE_NETHERRACK_CRYSTALLINE);
-
-		add(list, Blocks.BRICK_NETHERRACK);
-		add(list, Blocks.STAIRS_BRICK_NETHERRACK);
-		add(list, Blocks.SLAB_BRICK_NETHERRACK);
-
-		add(list, Blocks.NETHERRACK_POLISHED);
-		add(list, Blocks.SLAB_NETHERRACK_POLISHED);
-		add(list, Blocks.NETHERRACK_CARVED);
-
-
-		//GLOOMSTONE
-		add(list, Blocks.GLOOMSTONE);
-
-		add(list, Blocks.COBBLE_GLOOMSTONE);
-		add(list, Blocks.STAIRS_COBBLE_GLOOMSTONE);
-		add(list, Blocks.SLAB_COBBLE_GLOOMSTONE);
-
-		add(list, Blocks.BRICK_GLOOMSTONE);
-		add(list, Blocks.STAIRS_BRICK_GLOOMSTONE);
-		add(list, Blocks.SLAB_BRICK_GLOOMSTONE);
-
-		add(list, Blocks.GLOOMSTONE_POLISHED);
-		add(list, Blocks.SLAB_GLOOMSTONE_POLISHED);
-		add(list, Blocks.GLOOMSTONE_CARVED);
-
-
-		//MARBLE
-		add(list, Blocks.MARBLE);
-
-		add(list, Blocks.BRICK_MARBLE);
-		add(list, Blocks.STAIRS_BRICK_MARBLE);
-		add(list, Blocks.SLAB_BRICK_MARBLE);
-
-		add(list, Blocks.PILLAR_MARBLE);
-		add(list, Blocks.CAPSTONE_MARBLE);
-		add(list, Blocks.SLAB_CAPSTONE_MARBLE);
-
-
-		//SLATE
-		add(list, Blocks.SLATE);
-		add(list, Blocks.LAYER_SLATE);
-
-		add(list, Blocks.BRICK_SLATE);
-		add(list, Blocks.STAIRS_BRICK_SLATE);
-		add(list, Blocks.SLAB_BRICK_SLATE);
-
-		add(list, Blocks.SLATE_POLISHED);
-		add(list, Blocks.SLAB_SLATE_POLISHED);
-		add(list, Blocks.SLATE_CARVED);
-	}
-
-	public static void addWoodTypes(List<ItemStack> list) {
-		add(list, Blocks.PLANKS_OAK);
-		addPainted(list, Blocks.PLANKS_OAK_PAINTED, painted(Blocks.PLANKS_OAK_PAINTED));
-
-		add(list, Blocks.STAIRS_PLANKS_OAK);
-		addPainted(list, Blocks.STAIRS_PLANKS_PAINTED, painted(Blocks.STAIRS_PLANKS_PAINTED));
-		add(list, Blocks.SLAB_PLANKS_OAK);
-		addPainted(list, Blocks.SLAB_PLANKS_PAINTED, painted(Blocks.SLAB_PLANKS_PAINTED));
-
-		add(list, Blocks.FENCE_PLANKS_OAK);
-		addPainted(list, Blocks.FENCE_PLANKS_OAK_PAINTED, painted(Blocks.FENCE_PLANKS_OAK_PAINTED));
-
-		add(list, Blocks.FENCE_GATE_PLANKS_OAK);
-		addPainted(list, Blocks.FENCE_GATE_PLANKS_OAK_PAINTED, painted(Blocks.FENCE_GATE_PLANKS_OAK_PAINTED));
-
-		add(list, Blocks.TRAPDOOR_PLANKS_OAK);
-		addPainted(list, Blocks.TRAPDOOR_PLANKS_PAINTED, painted(Blocks.TRAPDOOR_PLANKS_PAINTED));
-	}
-
-	public static void addOrganicTypes(List<ItemStack> list) {
-		//LOGS
-		add(list, Blocks.LOG_OAK);
-		add(list, Blocks.LOG_OAK_MOSSY);
-		add(list, Blocks.LOG_PINE);
-		add(list, Blocks.LOG_BIRCH);
-		add(list, Blocks.LOG_CHERRY);
-		add(list, Blocks.LOG_EUCALYPTUS);
-		add(list, Blocks.LOG_THORN);
-		add(list, Blocks.LOG_PALM);
-		add(list, Blocks.LOG_SCORCHED);
-
-
-		//LEAVES
-		add(list, Blocks.LEAVES_OAK);
-		add(list, Blocks.LAYER_LEAVES_OAK);
-		add(list, Blocks.LEAVES_OAK_RETRO);
-		add(list, Blocks.LEAVES_PINE);
-		add(list, Blocks.LEAVES_BIRCH);
-		add(list, Blocks.LEAVES_CHERRY);
-		add(list, Blocks.LEAVES_CHERRY_FLOWERING);
-		add(list, Blocks.LEAVES_EUCALYPTUS);
-		add(list, Blocks.LEAVES_THORN);
-		add(list, Blocks.LEAVES_PALM);
-		add(list, Blocks.LEAVES_SHRUB);
-		add(list, Blocks.LEAVES_CACAO);
-
-
-		//SAPLINGS
-		add(list, Blocks.SAPLING_OAK);
-		add(list, Blocks.SAPLING_OAK_RETRO);
-		add(list, Blocks.SAPLING_PINE);
-		add(list, Blocks.SAPLING_BIRCH);
-		add(list, Blocks.SAPLING_CHERRY);
-		add(list, Blocks.SAPLING_EUCALYPTUS);
-		add(list, Blocks.SAPLING_THORN);
-		add(list, Blocks.SAPLING_PALM);
-		add(list, Blocks.SAPLING_SHRUB);
-		add(list, Blocks.SAPLING_CACAO);
-
-
-		//FLOWERS
-		list.add(new ItemStack(Blocks.FLOWER_YELLOW, 1, 0));
-//		list.add(new ItemStack(Blocks.FLOWER_YELLOW, 1, 32);
-//		list.add(new ItemStack(Blocks.FLOWER_YELLOW, 1, 64);
-//		list.add(new ItemStack(Blocks.FLOWER_YELLOW, 1, 96);
-
-		list.add(new ItemStack(Blocks.FLOWER_RED, 1, 0));
-//		list.add(new ItemStack(Blocks.FLOWER_RED, 1, 32);
-//		list.add(new ItemStack(Blocks.FLOWER_RED, 1, 64);
-//		list.add(new ItemStack(Blocks.FLOWER_RED, 1, 96);
-
-		list.add(new ItemStack(Blocks.FLOWER_PINK, 1, 0));
-//		list.add(new ItemStack(Blocks.FLOWER_PINK, 1, 32);
-//		list.add(new ItemStack(Blocks.FLOWER_PINK, 1, 64);
-//		list.add(new ItemStack(Blocks.FLOWER_PINK, 1, 96);
-
-		list.add(new ItemStack(Blocks.FLOWER_PURPLE, 1, 0));
-//		list.add(new ItemStack(Blocks.FLOWER_PURPLE, 1, 32);
-//		list.add(new ItemStack(Blocks.FLOWER_PURPLE, 1, 64);
-//		list.add(new ItemStack(Blocks.FLOWER_PURPLE, 1, 96);
-
-		list.add(new ItemStack(Blocks.FLOWER_LIGHT_BLUE, 1, 0));
-//		list.add(new ItemStack(Blocks.FLOWER_LIGHT_BLUE, 1, 32);
-//		list.add(new ItemStack(Blocks.FLOWER_LIGHT_BLUE, 1, 64);
-//		list.add(new ItemStack(Blocks.FLOWER_LIGHT_BLUE, 1, 96);
-
-		list.add(new ItemStack(Blocks.FLOWER_ORANGE, 1, 0));
-//		list.add(new ItemStack(Blocks.FLOWER_ORANGE, 1, 32);
-//		list.add(new ItemStack(Blocks.FLOWER_ORANGE, 1, 64);
-//		list.add(new ItemStack(Blocks.FLOWER_ORANGE, 1, 96);
-
-		add(list, Blocks.MUSHROOM_BROWN);
-		add(list, Blocks.MUSHROOM_RED);
-
-		//FOLIAGE
-		add(list, Blocks.TALLGRASS);
-		add(list, Blocks.TALLGRASS_FERN);
-		add(list, Blocks.DEADBUSH);
-		add(list, Blocks.SPINIFEX);
-		add(list, Blocks.ALGAE);
-		add(list, Blocks.CACTUS);
-
-		add(list, Blocks.PUMPKIN);
-		add(list, Blocks.PUMPKIN_CARVED_IDLE);
-		add(list, Blocks.PUMPKIN_CARVED_ACTIVE);
-
-		add(list, Blocks.BLOCK_SUGARCANE);
-		add(list, Blocks.BLOCK_SUGARCANE_BAKED);
-
-		add(list, Blocks.SPONGE_DRY);
-		add(list, Blocks.SPONGE_WET);
-
-		add(list, Blocks.PUMICE_DRY);
-		add(list, Blocks.PUMICE_WET);
-
-		add(list, Blocks.COBWEB);
-
-		add(list, Blocks.BONE_PILE);
-		add(list, Blocks.SOUL_CATCHER);
-		add(list, Blocks.BOULDER_MAGMATIC);
-		add(list, Blocks.BOULDER_SULFURIC);
-	}
-
-	public static void addNaturalTypes(List<ItemStack> list) {
-		add(list, Blocks.GRASS);
-		add(list, Blocks.GRASS_SCORCHED);
-		add(list, Blocks.GRASS_RETRO);
-
-		add(list, Blocks.DIRT);
-		add(list, Blocks.PATH_DIRT);
-		add(list, Blocks.FARMLAND_DIRT);
-
-		add(list, Blocks.DIRT_SCORCHED);
-		add(list, Blocks.DIRT_SCORCHED_RICH);
-
-		add(list, Blocks.MUD);
-		add(list, Blocks.MUD_BAKED);
-
-		add(list, Blocks.SAND);
-
-		add(list, Blocks.SANDSTONE);
-		add(list, Blocks.STAIRS_SANDSTONE);
-		add(list, Blocks.SLAB_SANDSTONE);
-
-		add(list, Blocks.BRICK_SANDSTONE);
-		add(list, Blocks.STAIRS_BRICK_SANDSTONE);
-		add(list, Blocks.SLAB_BRICK_SANDSTONE);
-
-		add(list, Blocks.GRAVEL);
-
-		add(list, Blocks.BRIMSAND);
-
-		add(list, Blocks.BRIMSTONE);
-		add(list, Blocks.BRIMTHAW);
-		add(list, Blocks.STAIRS_BRIMSTONE);
-		add(list, Blocks.SLAB_BRIMSTONE);
-
-		add(list, Blocks.BRICK_BRIMSTONE);
-		add(list, Blocks.STAIRS_BRICK_BRIMSTONE);
-		add(list, Blocks.SLAB_BRICK_BRIMSTONE);
-
-		add(list, Blocks.SULFUR);
-		add(list, Blocks.SULFUR_HARDENED);
-
-		add(list, Blocks.BLOCK_SNOW);
-		add(list, Blocks.LAYER_SNOW);
-
-		add(list, Blocks.BLOCK_ASH);
-		add(list, Blocks.LAYER_ASH);
-
-		add(list, Blocks.ICE);
-		add(list, Blocks.PERMAICE);
-
-		add(list, Blocks.BLOCK_CLAY);
-
-		add(list, Blocks.BRICK_CLAY);
-		add(list, Blocks.STAIRS_BRICK_CLAY);
-		add(list, Blocks.SLAB_BRICK_CLAY);
-
-		add(list, Blocks.OBSIDIAN);
-		add(list, Blocks.BONESHALE);
-		add(list, Blocks.BEDROCK);
-
-		add(list, Blocks.MAGMA);
-		add(list, Blocks.SOULSAND);
-		add(list, Blocks.SOULSCHIST);
-
-		add(list, Blocks.GLOWSTONE);
-
-		add(list, Blocks.THERMAL_VENT);
-
-		add(list, Blocks.EMBER);
-	}
-
-	public static void addRedstoneTypes(List<ItemStack> list) {
-		add(list, Blocks.TORCH_REDSTONE_ACTIVE);
-		add(list, Blocks.LEVER_COBBLE_STONE);
-
-		add(list, Blocks.BUTTON_STONE);
-		add(list, Blocks.BUTTON_BASALT);
-		add(list, Blocks.BUTTON_LIMESTONE);
-		add(list, Blocks.BUTTON_GRANITE);
-		add(list, Blocks.BUTTON_PERMAFROST);
-		add(list, Blocks.BUTTON_NETHERRACK);
-		add(list, Blocks.BUTTON_GLOOMSTONE);
-		add(list, Blocks.BUTTON_SANDSTONE);
-		add(list, Blocks.BUTTON_BRIMSTONE);
-		add(list, Blocks.BUTTON_PLANKS);
-		addPainted(list, Blocks.BUTTON_PLANKS_PAINTED, painted(Blocks.BUTTON_PLANKS_PAINTED));
-
-		add(list, Blocks.PRESSURE_PLATE_STONE);
-		add(list, Blocks.PRESSURE_PLATE_BASALT);
-		add(list, Blocks.PRESSURE_PLATE_LIMESTONE);
-		add(list, Blocks.PRESSURE_PLATE_GRANITE);
-		add(list, Blocks.PRESSURE_PLATE_PERMAFROST);
-		add(list, Blocks.PRESSURE_PLATE_NETHERRACK);
-		add(list, Blocks.PRESSURE_PLATE_GLOOMSTONE);
-		add(list, Blocks.PRESSURE_PLATE_SANDSTONE);
-		add(list, Blocks.PRESSURE_PLATE_BRIMSTONE);
-		add(list, Blocks.PRESSURE_PLATE_COBBLE_STONE);
-		add(list, Blocks.PRESSURE_PLATE_COBBLE_BASALT);
-		add(list, Blocks.PRESSURE_PLATE_COBBLE_LIMESTONE);
-		add(list, Blocks.PRESSURE_PLATE_COBBLE_GRANITE);
-		add(list, Blocks.PRESSURE_PLATE_COBBLE_PERMAFROST);
-		add(list, Blocks.PRESSURE_PLATE_COBBLE_NETHERRACK);
-		add(list, Blocks.PRESSURE_PLATE_COBBLE_GLOOMSTONE);
-		add(list, Blocks.PRESSURE_PLATE_PLANKS_OAK);
-		addPainted(list, Blocks.PRESSURE_PLATE_PLANKS_OAK_PAINTED, painted(Blocks.PRESSURE_PLATE_PLANKS_OAK_PAINTED));
-
-		add(list, Blocks.PISTON_BASE);
-		add(list, Blocks.PISTON_BASE_STICKY);
-		add(list, Blocks.PISTON_BASE_STEEL);
-
-		add(list, Blocks.DISPENSER_COBBLE_STONE);
-		add(list, Blocks.MOTION_SENSOR_IDLE);
-		add(list, Blocks.ACTIVATOR);
-		add(list, Blocks.MATCHER);
-
-		add(list, Blocks.PUMPKIN_REDSTONE);
-
-		add(list, Blocks.RUBYGLASS_COLUMN);
-		add(list, Blocks.RUBYGLASS_NODE);
-		add(list, Blocks.BLOCK_RUBYGLASS);
-		add(list, Blocks.CONDUIT);
-		add(list, Blocks.RUBYGLASS_GROWTH);
-		add(list, Blocks.RUBYGLASS_CRYSTAL);
-
-		add(list, Blocks.BRAZIER_INACTIVE);
-
-		add(list, Blocks.MESH);
-		add(list, Blocks.MESH_GOLD);
-
-		add(list, Blocks.MOBSPAWNER);
-		add(list, Blocks.MOBSPAWNER_DEACTIVATED);
-
-		add(list, Blocks.NOTEBLOCK);
-		add(list, Blocks.JUKEBOX);
-
-		add(list, Blocks.RAIL);
-		add(list, Blocks.RAIL_POWERED);
-		add(list, Blocks.RAIL_DETECTOR);
-
-		add(list, Blocks.TNT);
-		add(list, Blocks.SPIKES);
-
-		add(list, Blocks.TRAPDOOR_IRON);
-		add(list, Blocks.TRAPDOOR_STEEL);
-
-		addPainted(list, Blocks.LAMP_IDLE, painted(Blocks.LAMP_IDLE));
-	}
-
-	public static void addOreTypes(List<ItemStack> list) {
-		add(list, Blocks.ORE_COAL_STONE);
-		add(list, Blocks.ORE_COAL_BASALT);
-		add(list, Blocks.ORE_COAL_LIMESTONE);
-		add(list, Blocks.ORE_COAL_GRANITE);
-		add(list, Blocks.ORE_COAL_PERMAFROST);
-
-		add(list, Blocks.ORE_IRON_STONE);
-		add(list, Blocks.ORE_IRON_BASALT);
-		add(list, Blocks.ORE_IRON_LIMESTONE);
-		add(list, Blocks.ORE_IRON_GRANITE);
-		add(list, Blocks.ORE_IRON_PERMAFROST);
-
-		add(list, Blocks.ORE_GOLD_STONE);
-		add(list, Blocks.ORE_GOLD_BASALT);
-		add(list, Blocks.ORE_GOLD_LIMESTONE);
-		add(list, Blocks.ORE_GOLD_GRANITE);
-		add(list, Blocks.ORE_GOLD_PERMAFROST);
-
-		add(list, Blocks.ORE_LAPIS_STONE);
-		add(list, Blocks.ORE_LAPIS_BASALT);
-		add(list, Blocks.ORE_LAPIS_LIMESTONE);
-		add(list, Blocks.ORE_LAPIS_GRANITE);
-		add(list, Blocks.ORE_LAPIS_PERMAFROST);
-
-		add(list, Blocks.ORE_REDSTONE_STONE);
-		add(list, Blocks.ORE_REDSTONE_BASALT);
-		add(list, Blocks.ORE_REDSTONE_LIMESTONE);
-		add(list, Blocks.ORE_REDSTONE_GRANITE);
-		add(list, Blocks.ORE_REDSTONE_PERMAFROST);
-
-		add(list, Blocks.ORE_DIAMOND_STONE);
-		add(list, Blocks.ORE_DIAMOND_BASALT);
-		add(list, Blocks.ORE_DIAMOND_LIMESTONE);
-		add(list, Blocks.ORE_DIAMOND_GRANITE);
-		add(list, Blocks.ORE_DIAMOND_PERMAFROST);
-
-		add(list, Blocks.ORE_NETHERCOAL_BASALT);
-		add(list, Blocks.ORE_NETHERCOAL_NETHERRACK);
-		add(list, Blocks.ORE_NETHERCOAL_GLOOMSTONE);
-	}
-
-	public static void addStorageTypes(List<ItemStack> list) {
-		add(list, Blocks.BLOCK_IRON);
-		add(list, Blocks.BLOCK_STEEL);
-		add(list, Blocks.BLOCK_GOLD);
-		add(list, Blocks.BLOCK_LAPIS);
-		add(list, Blocks.BLOCK_REDSTONE);
-		add(list, Blocks.BLOCK_DIAMOND);
-		add(list, Blocks.BLOCK_QUARTZ);
-
-		add(list, Blocks.BLOCK_COAL);
-		add(list, Blocks.BLOCK_CHARCOAL);
-		add(list, Blocks.BLOCK_NETHER_COAL);
-		add(list, Blocks.BLOCK_OLIVINE);
-
-		add(list, Blocks.BRICK_IRON);
-		add(list, Blocks.STAIRS_BRICK_IRON);
-		add(list, Blocks.SLAB_BRICK_IRON);
-
-		add(list, Blocks.BRICK_STEEL);
-		add(list, Blocks.STAIRS_BRICK_STEEL);
-		add(list, Blocks.SLAB_BRICK_STEEL);
-
-		add(list, Blocks.BRICK_GOLD);
-		add(list, Blocks.STAIRS_BRICK_GOLD);
-		add(list, Blocks.SLAB_BRICK_GOLD);
-
-		add(list, Blocks.BRICK_LAPIS);
-		add(list, Blocks.STAIRS_BRICK_LAPIS);
-		add(list, Blocks.SLAB_BRICK_LAPIS);
-
-		add(list, Blocks.BRICK_DIAMOND);
-		add(list, Blocks.STAIRS_BRICK_DIAMOND);
-		add(list, Blocks.SLAB_BRICK_DIAMOND);
-
-		add(list, Blocks.BRICK_QUARTZ);
-		add(list, Blocks.STAIRS_BRICK_QUARTZ);
-		add(list, Blocks.SLAB_BRICK_QUARTZ);
-
-		add(list, Blocks.BRICK_OLIVINE);
-		add(list, Blocks.STAIRS_BRICK_OLIVINE);
-		add(list, Blocks.SLAB_BRICK_OLIVINE);
-
-		add(list, Blocks.BRICK_RUBYGLASS);
-		add(list, Blocks.STAIRS_BRICK_RUBYGLASS);
-		add(list, Blocks.SLAB_BRICK_RUBYGLASS);
-
-	}
-
-	private static void addPainted(List<ItemStack> list, Block<?> block, IPainted painted) {
-		for (DyeColor color : RAINBOW_ORDER) {
-			list.add(new ItemStack(block, 1, painted.toMetadata(color)));
-		}
-	}
-
-	private static void add(List<ItemStack> list, Block<?>... blocks) {
-		for (Block<?> block : blocks) {
-			list.add(new ItemStack(block));
-		}
-	}
-
-	private static IPainted painted(Block<?> block) {
-		return (IPainted) block.getLogic();
-	}
-
-}
-
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeItems.java b/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeItems.java
deleted file mode 100644
index 959f19131..000000000
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeItems.java
+++ /dev/null
@@ -1,331 +0,0 @@
-package net.minecraft.core.player.inventory;
-
-import net.minecraft.core.item.Item;
-import net.minecraft.core.item.ItemBucket;
-import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.item.Items;
-import net.minecraft.core.util.collection.NamespaceID;
-import net.minecraft.core.util.helper.DyeColor;
-
-import java.util.List;
-
-public final class CreativeItems {
-
-	private static final DyeColor[] RAINBOW_ORDER = {
-		DyeColor.RED,
-		DyeColor.ORANGE,
-		DyeColor.YELLOW,
-		DyeColor.LIME,
-		DyeColor.GREEN,
-		DyeColor.CYAN,
-		DyeColor.LIGHT_BLUE,
-		DyeColor.BLUE,
-		DyeColor.PURPLE,
-		DyeColor.MAGENTA,
-		DyeColor.PINK,
-		DyeColor.BROWN,
-		DyeColor.WHITE,
-		DyeColor.SILVER,
-		DyeColor.GRAY,
-		DyeColor.BLACK
-	};
-
-	private static void addBucketVariants(List<ItemStack> out, Item item) {
-		if (item instanceof ItemBucket itemBucket) {
-			out.add(new ItemStack(item));
-			for (NamespaceID stateId : ItemBucket.getRegisteredStateIds()) {
-				if (!ItemBucket.STATE_EMPTY.equals(stateId)) {
-					ItemStack itemStack = new ItemStack(item, 1);
-					ItemBucket.setState(itemStack, stateId);
-					ItemBucket.setCharges(itemStack, itemBucket.maxCharges);
-					out.add(itemStack);
-				}
-			}
-		}
-	}
-
-	public static void populate(List<ItemStack> out) {
-
-		//TOOLS
-		out.add(new ItemStack(Items.TOOL_SHOVEL_WOOD));
-		out.add(new ItemStack(Items.TOOL_PICKAXE_WOOD));
-		out.add(new ItemStack(Items.TOOL_AXE_WOOD));
-		out.add(new ItemStack(Items.TOOL_HOE_WOOD));
-		out.add(new ItemStack(Items.TOOL_SWORD_WOOD));
-
-		out.add(new ItemStack(Items.TOOL_SHOVEL_STONE));
-		out.add(new ItemStack(Items.TOOL_PICKAXE_STONE));
-		out.add(new ItemStack(Items.TOOL_AXE_STONE));
-		out.add(new ItemStack(Items.TOOL_HOE_STONE));
-		out.add(new ItemStack(Items.TOOL_SWORD_STONE));
-
-		out.add(new ItemStack(Items.TOOL_SHOVEL_IRON));
-		out.add(new ItemStack(Items.TOOL_PICKAXE_IRON));
-		out.add(new ItemStack(Items.TOOL_AXE_IRON));
-		out.add(new ItemStack(Items.TOOL_HOE_IRON));
-		out.add(new ItemStack(Items.TOOL_SWORD_IRON));
-
-		out.add(new ItemStack(Items.TOOL_SHOVEL_GOLD));
-		out.add(new ItemStack(Items.TOOL_PICKAXE_GOLD));
-		out.add(new ItemStack(Items.TOOL_AXE_GOLD));
-		out.add(new ItemStack(Items.TOOL_HOE_GOLD));
-		out.add(new ItemStack(Items.TOOL_SWORD_GOLD));
-
-		out.add(new ItemStack(Items.TOOL_SHOVEL_DIAMOND));
-		out.add(new ItemStack(Items.TOOL_PICKAXE_DIAMOND));
-		out.add(new ItemStack(Items.TOOL_AXE_DIAMOND));
-		out.add(new ItemStack(Items.TOOL_HOE_DIAMOND));
-		out.add(new ItemStack(Items.TOOL_SWORD_DIAMOND));
-
-		out.add(new ItemStack(Items.TOOL_SHOVEL_STEEL));
-		out.add(new ItemStack(Items.TOOL_PICKAXE_STEEL));
-		out.add(new ItemStack(Items.TOOL_AXE_STEEL));
-		out.add(new ItemStack(Items.TOOL_HOE_STEEL));
-		out.add(new ItemStack(Items.TOOL_SWORD_STEEL));
-
-
-		//MISC TOOLS
-		out.add(new ItemStack(Items.TOOL_FIRESTRIKER_IRON));
-		out.add(new ItemStack(Items.TOOL_FIRESTRIKER_STEEL));
-
-		out.add(new ItemStack(Items.TOOL_SHEARS));
-		out.add(new ItemStack(Items.TOOL_SHEARS_STEEL));
-
-		addBucketVariants(out, Items.BUCKET_IRON);
-		addBucketVariants(out, Items.BUCKET_STEEL);
-
-		out.add(new ItemStack(Items.PAINTBRUSH));
-
-		out.add(new ItemStack(Items.TOOL_FISHINGROD));
-
-		out.add(new ItemStack(Items.TOOL_BOW));
-		out.add(new ItemStack(Items.AMMO_ARROW));
-		out.add(new ItemStack(Items.AMMO_ARROW_GOLD));
-		out.add(new ItemStack(Items.AMMO_ARROW_PURPLE));
-		out.add(new ItemStack(Items.AMMO_ARROW_FLAMING));
-
-		out.add(new ItemStack(Items.HANDCANNON_UNLOADED));
-		out.add(new ItemStack(Items.AMMO_CHARGE_EXPLOSIVE));
-
-		out.add(new ItemStack(Items.AMMO_FIREBALL));
-
-		out.add(new ItemStack(Items.TOOL_COMPASS));
-		out.add(new ItemStack(Items.TOOL_CLOCK));
-		out.add(new ItemStack(Items.TOOL_CALENDAR));
-		out.add(new ItemStack(Items.MAP));
-
-		out.add(new ItemStack(Items.ROPE));
-
-		out.add(new ItemStack(Items.LABEL));
-
-		out.add(new ItemStack(Items.WAND_MONSTER_SPAWNER));
-		out.add(new ItemStack(Items.WAND_NBT));
-
-
-		//ARMOR
-		out.add(new ItemStack(Items.ARMOR_HELMET_LEATHER));
-		out.add(new ItemStack(Items.ARMOR_CHESTPLATE_LEATHER));
-		out.add(new ItemStack(Items.ARMOR_LEGGINGS_LEATHER));
-		out.add(new ItemStack(Items.ARMOR_BOOTS_LEATHER));
-
-		out.add(new ItemStack(Items.ARMOR_HELMET_CHAINMAIL));
-		out.add(new ItemStack(Items.ARMOR_CHESTPLATE_CHAINMAIL));
-		out.add(new ItemStack(Items.ARMOR_LEGGINGS_CHAINMAIL));
-		out.add(new ItemStack(Items.ARMOR_BOOTS_CHAINMAIL));
-
-		out.add(new ItemStack(Items.ARMOR_HELMET_IRON));
-		out.add(new ItemStack(Items.ARMOR_CHESTPLATE_IRON));
-		out.add(new ItemStack(Items.ARMOR_LEGGINGS_IRON));
-		out.add(new ItemStack(Items.ARMOR_BOOTS_IRON));
-
-		out.add(new ItemStack(Items.ARMOR_HELMET_GOLD));
-		out.add(new ItemStack(Items.ARMOR_CHESTPLATE_GOLD));
-		out.add(new ItemStack(Items.ARMOR_LEGGINGS_GOLD));
-		out.add(new ItemStack(Items.ARMOR_BOOTS_GOLD));
-
-		out.add(new ItemStack(Items.ARMOR_HELMET_DIAMOND));
-		out.add(new ItemStack(Items.ARMOR_CHESTPLATE_DIAMOND));
-		out.add(new ItemStack(Items.ARMOR_LEGGINGS_DIAMOND));
-		out.add(new ItemStack(Items.ARMOR_BOOTS_DIAMOND));
-
-		out.add(new ItemStack(Items.ARMOR_HELMET_STEEL));
-		out.add(new ItemStack(Items.ARMOR_CHESTPLATE_STEEL));
-		out.add(new ItemStack(Items.ARMOR_LEGGINGS_STEEL));
-		out.add(new ItemStack(Items.ARMOR_BOOTS_STEEL));
-
-		out.add(new ItemStack(Items.ARMOR_QUIVER));
-		out.add(new ItemStack(Items.ARMOR_QUIVER_GOLD));
-		out.add(new ItemStack(Items.ARMOR_BOOTS_ICESKATES));
-
-		out.add(new ItemStack(Items.ARMOR_WOLF_LEATHER));
-		out.add(new ItemStack(Items.ARMOR_WOLF_CHAINMAIL));
-		out.add(new ItemStack(Items.ARMOR_WOLF_IRON));
-		out.add(new ItemStack(Items.ARMOR_WOLF_GOLD));
-		out.add(new ItemStack(Items.ARMOR_WOLF_DIAMOND));
-		out.add(new ItemStack(Items.ARMOR_WOLF_STEEL));
-
-
-		//FOOD
-		out.add(new ItemStack(Items.FOOD_APPLE));
-		out.add(new ItemStack(Items.FOOD_APPLE_GOLD));
-
-		out.add(new ItemStack(Items.FOOD_CHERRY));
-
-		out.add(new ItemStack(Items.FOOD_PORKCHOP_RAW));
-		out.add(new ItemStack(Items.FOOD_PORKCHOP_COOKED));
-
-		out.add(new ItemStack(Items.FOOD_VENISON_RAW));
-		out.add(new ItemStack(Items.FOOD_VENISON_COOKED));
-
-		out.add(new ItemStack(Items.FOOD_FISH_RAW));
-		out.add(new ItemStack(Items.FOOD_FISH_COOKED));
-
-		out.add(new ItemStack(Items.DUST_SUGAR));
-		out.add(new ItemStack(Items.EGG_CHICKEN));
-
-		out.add(new ItemStack(Items.SEEDS_WHEAT));
-		out.add(new ItemStack(Items.SEEDS_PUMPKIN));
-
-		out.add(new ItemStack(Items.WHEAT));
-		out.add(new ItemStack(Items.DOUGH));
-		out.add(new ItemStack(Items.FOOD_BREAD));
-
-		out.add(new ItemStack(Items.FOOD_COOKIE));
-		out.add(new ItemStack(Items.FOOD_CAKE));
-		out.add(new ItemStack(Items.FOOD_PUMPKIN_PIE));
-
-		out.add(new ItemStack(Items.BOWL));
-		out.add(new ItemStack(Items.FOOD_STEW_MUSHROOM));
-
-
-		//ORE
-		out.add(new ItemStack(Items.AMMO_PEBBLE));
-
-		out.add(new ItemStack(Items.COAL));
-		out.add(new ItemStack(Items.COAL, 1, 1));
-		out.add(new ItemStack(Items.NETHERCOAL));
-		out.add(new ItemStack(Items.OLIVINE));
-
-		out.add(new ItemStack(Items.ORE_RAW_IRON));
-		out.add(new ItemStack(Items.INGOT_IRON));
-
-		out.add(new ItemStack(Items.DIAMOND));
-
-		out.add(new ItemStack(Items.INGOT_STEEL_CRUDE));
-		out.add(new ItemStack(Items.INGOT_STEEL));
-
-		out.add(new ItemStack(Items.ORE_RAW_GOLD));
-		out.add(new ItemStack(Items.INGOT_GOLD));
-
-		out.add(new ItemStack(Items.DUST_REDSTONE));
-
-		out.add(new ItemStack(Items.REPEATER));
-
-		out.add(new ItemStack(Items.TIMER));
-
-		out.add(new ItemStack(Items.QUARTZ));
-
-		out.add(new ItemStack(Items.FLINT));
-		out.add(new ItemStack(Items.CLAY));
-		out.add(new ItemStack(Items.BRICK_CLAY));
-
-		out.add(new ItemStack(Items.DUST_GLOWSTONE));
-
-		out.add(new ItemStack(Items.RUBYGLASS));
-
-		out.add(new ItemStack(Items.SULFUR));
-
-
-		//Materials
-		out.add(new ItemStack(Items.STICK));
-		out.add(new ItemStack(Items.AMMO_SNOWBALL));
-		out.add(new ItemStack(Items.SUGARCANE));
-		out.add(new ItemStack(Items.PAPER));
-		out.add(new ItemStack(Items.BOOK));
-		for (DyeColor color : RAINBOW_ORDER) {
-			int meta = color.itemMeta;
-			out.add(new ItemStack(Items.DYE, 1, meta));
-		}
-
-		//Mob Drops
-		out.add(new ItemStack(Items.CLOTH));
-		out.add(new ItemStack(Items.STRING));
-		out.add(new ItemStack(Items.FEATHER_CHICKEN));
-		out.add(new ItemStack(Items.GUNPOWDER));
-		out.add(new ItemStack(Items.BONE));
-		out.add(new ItemStack(Items.CHAINLINK));
-		out.add(new ItemStack(Items.SLIMEBALL));
-		out.add(new ItemStack(Items.LEATHER));
-
-		//Placeables
-		out.add(new ItemStack(Items.PAINTING));
-
-		out.add(new ItemStack(Items.DOOR_OAK));
-		for (DyeColor color : RAINBOW_ORDER) {
-			int meta = color.itemMeta;
-			out.add(new ItemStack(Items.DOOR_OAK_PAINTED, 1, meta));
-		}
-
-		out.add(new ItemStack(Items.DOOR_GLASS));
-		out.add(new ItemStack(Items.DOOR_IRON));
-		out.add(new ItemStack(Items.DOOR_STEEL));
-
-		out.add(new ItemStack(Items.SIGN));
-		for (DyeColor color : RAINBOW_ORDER) {
-			int meta = color.itemMeta;
-			out.add(new ItemStack(Items.SIGN_PAINTED, 1, meta));
-		}
-
-		out.add(new ItemStack(Items.FLAG));
-		out.add(new ItemStack(Items.BED));
-		out.add(new ItemStack(Items.SEAT));
-
-		out.add(new ItemStack(Items.BASKET));
-
-		out.add(new ItemStack(Items.JAR));
-
-		out.add(new ItemStack(Items.LANTERN_FIREFLY_GREEN));
-		out.add(new ItemStack(Items.LANTERN_FIREFLY_BLUE));
-		out.add(new ItemStack(Items.LANTERN_FIREFLY_ORANGE));
-		out.add(new ItemStack(Items.LANTERN_FIREFLY_RED));
-
-		out.add(new ItemStack(Items.JAR_BUTTERFLY_BLUE));
-		out.add(new ItemStack(Items.JAR_BUTTERFLY_ORANGE));
-		out.add(new ItemStack(Items.JAR_BUTTERFLY_PINK));
-		out.add(new ItemStack(Items.JAR_BUTTERFLY_SILVER));
-
-		out.add(new ItemStack(Items.STATUE_STONE));
-		out.add(new ItemStack(Items.STATUE_BASALT));
-		out.add(new ItemStack(Items.STATUE_LIMESTONE));
-		out.add(new ItemStack(Items.STATUE_GRANITE));
-		out.add(new ItemStack(Items.STATUE_PERMAFROST));
-		out.add(new ItemStack(Items.STATUE_MARBLE));
-		out.add(new ItemStack(Items.STATUE_SLATE));
-		out.add(new ItemStack(Items.STATUE_NETHERRACK));
-		out.add(new ItemStack(Items.STATUE_GLOOMSTONE));
-		out.add(new ItemStack(Items.STATUE_PIGMAN));
-
-		out.add(new ItemStack(Items.SADDLE));
-
-		out.add(new ItemStack(Items.BOAT));
-
-		out.add(new ItemStack(Items.MINECART));
-		out.add(new ItemStack(Items.MINECART_CHEST));
-		out.add(new ItemStack(Items.MINECART_FURNACE));
-
-		// Records
-		out.add(new ItemStack(Items.RECORD_13));
-		out.add(new ItemStack(Items.RECORD_CAT));
-
-		out.add(new ItemStack(Items.RECORD_BLOCKS));
-		out.add(new ItemStack(Items.RECORD_CHIRP));
-		out.add(new ItemStack(Items.RECORD_FAR));
-		out.add(new ItemStack(Items.RECORD_MALL));
-		out.add(new ItemStack(Items.RECORD_MELLOHI));
-		out.add(new ItemStack(Items.RECORD_STAL));
-		out.add(new ItemStack(Items.RECORD_STRAD));
-		out.add(new ItemStack(Items.RECORD_WARD));
-		out.add(new ItemStack(Items.RECORD_WAIT));
-		out.add(new ItemStack(Items.RECORD_DOG));
-	}
-}
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeMenuContents.java b/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeMenuContents.java
new file mode 100644
index 000000000..176cf952c
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeMenuContents.java
@@ -0,0 +1,930 @@
+package net.minecraft.core.player.inventory;
+
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.IPainted;
+import net.minecraft.core.item.Item;
+import net.minecraft.core.item.ItemBucket;
+import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.item.Items;
+import net.minecraft.core.util.collection.NamespaceID;
+import net.minecraft.core.util.helper.DyeColor;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+import static net.minecraft.core.player.inventory.menu.MenuInventoryCreative.CREATIVE_COLUMNS;
+import static net.minecraft.core.player.inventory.menu.MenuInventoryCreative.CREATIVE_PAGE_SIZE;
+
+public final class CreativeMenuContents {
+
+	private static final DyeColor[] RAINBOW_ORDER = {
+		DyeColor.RED,
+		DyeColor.ORANGE,
+		DyeColor.YELLOW,
+		DyeColor.LIME,
+		DyeColor.GREEN,
+		DyeColor.CYAN,
+		DyeColor.LIGHT_BLUE,
+		DyeColor.BLUE,
+		DyeColor.PURPLE,
+		DyeColor.MAGENTA,
+		DyeColor.PINK,
+		DyeColor.BROWN,
+		DyeColor.WHITE,
+		DyeColor.SILVER,
+		DyeColor.GRAY,
+		DyeColor.BLACK
+	};
+
+	public CreativeMenuContents() {
+	}
+
+	/** Inserts {@code count} empty slots into the creative grid at the current catalog position. */
+	public static void addGap(List<ItemStack> list, int count) {
+		for (int i = 0; i < count; i++) {
+			list.add(null);
+		}
+	}
+
+	/**
+	 * Pads the creative inventory line until the next line is reached. If no spaces need to be filled, nothing happens.
+	 */
+	public static void newLine(@NotNull List<ItemStack> list) {
+		int remainder = list.size() % CREATIVE_COLUMNS;
+		if (remainder != 0) {
+			addGap(list, CREATIVE_COLUMNS - remainder);
+		}
+	}
+
+	/**
+	 * Pads the creative inventory until the next page is reached.
+	 */
+	public static void newPage(@NotNull List<ItemStack> list) {
+		int n = list.size();
+		if (n == 0) {
+			return;
+		}
+		int rem = n % CREATIVE_PAGE_SIZE;
+		if (rem != 0) {
+			addGap(list, CREATIVE_PAGE_SIZE - rem);
+		}
+	}
+
+	public static void populate(List<ItemStack> list) {
+		addNaturalTypes(list);
+		newPage(list);
+
+		addStoneTypes(list);
+		newPage(list);
+
+		addOreTypes(list);
+		newPage(list);
+
+		addRedstoneTypes(list);
+		newPage(list);
+
+		addLogTypes(list);
+		newLine(list);
+		addWoodTypes(list);
+		newPage(list);
+
+		addPaintedTypes(list);
+
+		addOrganicTypes(list);
+		newPage(list);
+
+		addWorkstationsAndGlass(list);
+		newPage(list);
+
+		addTools(list);
+		newPage(list);
+
+		addArmor(list);
+		newPage(list);
+
+		addMiscTools(list);
+		newPage(list);
+
+		addFood(list);
+		newPage(list);
+
+		addDyes(list);
+		newPage(list);
+
+		addOreProducts(list);
+		addBasics(list);
+		addMobDrops(list);
+		newPage(list);
+
+		addStorageTypes(list);
+		newPage(list);
+
+		addPlaceables(list);
+		newPage(list);
+
+		addRecords(list);
+		newPage(list);
+	}
+
+	private static void addTools(@NotNull List<ItemStack> list) {
+		list.add(new ItemStack(Items.TOOL_SHOVEL_WOOD));
+		list.add(new ItemStack(Items.TOOL_PICKAXE_WOOD));
+		list.add(new ItemStack(Items.TOOL_AXE_WOOD));
+		list.add(new ItemStack(Items.TOOL_HOE_WOOD));
+		list.add(new ItemStack(Items.TOOL_SWORD_WOOD));
+		newLine(list);
+
+		list.add(new ItemStack(Items.TOOL_SHOVEL_STONE));
+		list.add(new ItemStack(Items.TOOL_PICKAXE_STONE));
+		list.add(new ItemStack(Items.TOOL_AXE_STONE));
+		list.add(new ItemStack(Items.TOOL_HOE_STONE));
+		list.add(new ItemStack(Items.TOOL_SWORD_STONE));
+		newLine(list);
+
+		list.add(new ItemStack(Items.TOOL_SHOVEL_IRON));
+		list.add(new ItemStack(Items.TOOL_PICKAXE_IRON));
+		list.add(new ItemStack(Items.TOOL_AXE_IRON));
+		list.add(new ItemStack(Items.TOOL_HOE_IRON));
+		list.add(new ItemStack(Items.TOOL_SWORD_IRON));
+		newLine(list);
+
+		list.add(new ItemStack(Items.TOOL_SHOVEL_GOLD));
+		list.add(new ItemStack(Items.TOOL_PICKAXE_GOLD));
+		list.add(new ItemStack(Items.TOOL_AXE_GOLD));
+		list.add(new ItemStack(Items.TOOL_HOE_GOLD));
+		list.add(new ItemStack(Items.TOOL_SWORD_GOLD));
+		newLine(list);
+
+		list.add(new ItemStack(Items.TOOL_SHOVEL_DIAMOND));
+		list.add(new ItemStack(Items.TOOL_PICKAXE_DIAMOND));
+		list.add(new ItemStack(Items.TOOL_AXE_DIAMOND));
+		list.add(new ItemStack(Items.TOOL_HOE_DIAMOND));
+		list.add(new ItemStack(Items.TOOL_SWORD_DIAMOND));
+		newLine(list);
+
+		list.add(new ItemStack(Items.TOOL_SHOVEL_STEEL));
+		list.add(new ItemStack(Items.TOOL_PICKAXE_STEEL));
+		list.add(new ItemStack(Items.TOOL_AXE_STEEL));
+		list.add(new ItemStack(Items.TOOL_HOE_STEEL));
+		list.add(new ItemStack(Items.TOOL_SWORD_STEEL));
+	}
+
+	private static void addMiscTools(@NotNull List<ItemStack> list) {
+		list.add(new ItemStack(Items.TOOL_FIRESTRIKER_IRON));
+		list.add(new ItemStack(Items.TOOL_FIRESTRIKER_STEEL));
+
+		list.add(new ItemStack(Items.TOOL_SHEARS));
+		list.add(new ItemStack(Items.TOOL_SHEARS_STEEL));
+		newLine(list);
+
+		addBucketVariants(list, Items.BUCKET_IRON);
+		newLine(list);
+		addBucketVariants(list, Items.BUCKET_STEEL);
+		newLine(list);
+
+		list.add(new ItemStack(Items.PAINTBRUSH));
+		list.add(new ItemStack(Items.WAND_MONSTER_SPAWNER));
+		list.add(new ItemStack(Items.WAND_NBT));
+		list.add(new ItemStack(Items.TOOL_FISHINGROD));
+		newLine(list);
+
+		list.add(new ItemStack(Items.TOOL_BOW));
+		list.add(new ItemStack(Items.AMMO_ARROW));
+		list.add(new ItemStack(Items.AMMO_ARROW_GOLD));
+		list.add(new ItemStack(Items.AMMO_ARROW_FLAMING));
+		newLine(list);
+
+		list.add(new ItemStack(Items.HANDCANNON_UNLOADED));
+		list.add(new ItemStack(Items.AMMO_CHARGE_EXPLOSIVE));
+		list.add(new ItemStack(Items.AMMO_FIREBALL));
+		newLine(list);
+
+		list.add(new ItemStack(Items.TOOL_COMPASS));
+		list.add(new ItemStack(Items.TOOL_CLOCK));
+		list.add(new ItemStack(Items.TOOL_CALENDAR));
+		list.add(new ItemStack(Items.MAP));
+		list.add(new ItemStack(Items.ROPE));
+		list.add(new ItemStack(Items.LABEL));
+		newLine(list);
+	}
+
+	private static void addStoneTypes(List<ItemStack> list) {
+		addBlock(list, Blocks.STONE);
+		addBlock(list, Blocks.MOSS_STONE);
+		addBlock(list, Blocks.COBBLE_STONE);
+		addBlock(list, Blocks.STAIRS_COBBLE_STONE);
+		addBlock(list, Blocks.SLAB_COBBLE_STONE);
+		addBlock(list, Blocks.COBBLE_STONE_MOSSY);
+
+		addBlock(list, Blocks.BRICK_STONE);
+		addBlock(list, Blocks.STAIRS_BRICK_STONE);
+		addBlock(list, Blocks.SLAB_BRICK_STONE);
+
+		addBlock(list, Blocks.STONE_POLISHED);
+		addBlock(list, Blocks.SLAB_STONE_POLISHED);
+
+		addBlock(list, Blocks.BRICK_STONE_POLISHED);
+		addBlock(list, Blocks.STAIRS_BRICK_STONE_POLISHED);
+		addBlock(list, Blocks.SLAB_BRICK_STONE_POLISHED);
+		addBlock(list, Blocks.BRICK_STONE_POLISHED_MOSSY);
+		list.add(new ItemStack(Items.STATUE_STONE));
+		addBlock(list, Blocks.BUTTON_STONE);
+		addBlock(list, Blocks.PRESSURE_PLATE_STONE);
+		addBlock(list, Blocks.PRESSURE_PLATE_COBBLE_STONE);
+		newPage(list);
+
+		addBlock(list, Blocks.BASALT);
+		addBlock(list, Blocks.MOSS_BASALT);
+
+		addBlock(list, Blocks.COBBLE_BASALT);
+		addBlock(list, Blocks.STAIRS_COBBLE_BASALT);
+		addBlock(list, Blocks.SLAB_COBBLE_BASALT);
+		addBlock(list, Blocks.COBBLE_BASALT_MOSSY);
+
+		addBlock(list, Blocks.BRICK_BASALT);
+		addBlock(list, Blocks.STAIRS_BRICK_BASALT);
+		addBlock(list, Blocks.SLAB_BRICK_BASALT);
+
+		addBlock(list, Blocks.BASALT_POLISHED);
+		addBlock(list, Blocks.SLAB_BASALT_POLISHED);
+		list.add(new ItemStack(Items.STATUE_BASALT));
+		addBlock(list, Blocks.BUTTON_BASALT);
+		addBlock(list, Blocks.PRESSURE_PLATE_BASALT);
+		addBlock(list, Blocks.PRESSURE_PLATE_COBBLE_BASALT);
+		newPage(list);
+
+		addBlock(list, Blocks.LIMESTONE);
+		addBlock(list, Blocks.MOSS_LIMESTONE);
+
+		addBlock(list, Blocks.COBBLE_LIMESTONE);
+		addBlock(list, Blocks.STAIRS_COBBLE_LIMESTONE);
+		addBlock(list, Blocks.SLAB_COBBLE_LIMESTONE);
+		addBlock(list, Blocks.COBBLE_LIMESTONE_MOSSY);
+
+		addBlock(list, Blocks.BRICK_LIMESTONE);
+		addBlock(list, Blocks.STAIRS_BRICK_LIMESTONE);
+		addBlock(list, Blocks.SLAB_BRICK_LIMESTONE);
+
+		addBlock(list, Blocks.LIMESTONE_POLISHED);
+		addBlock(list, Blocks.SLAB_LIMESTONE_POLISHED);
+		list.add(new ItemStack(Items.STATUE_LIMESTONE));
+		addBlock(list, Blocks.BUTTON_LIMESTONE);
+		addBlock(list, Blocks.PRESSURE_PLATE_LIMESTONE);
+		addBlock(list, Blocks.PRESSURE_PLATE_COBBLE_LIMESTONE);
+		newPage(list);
+
+		addBlock(list, Blocks.GRANITE);
+		addBlock(list, Blocks.MOSS_GRANITE);
+
+		addBlock(list, Blocks.COBBLE_GRANITE);
+		addBlock(list, Blocks.STAIRS_COBBLE_GRANITE);
+		addBlock(list, Blocks.SLAB_COBBLE_GRANITE);
+		addBlock(list, Blocks.COBBLE_GRANITE_MOSSY);
+
+		addBlock(list, Blocks.BRICK_GRANITE);
+		addBlock(list, Blocks.STAIRS_BRICK_GRANITE);
+		addBlock(list, Blocks.SLAB_BRICK_GRANITE);
+
+		addBlock(list, Blocks.GRANITE_POLISHED);
+		addBlock(list, Blocks.SLAB_GRANITE_POLISHED);
+		list.add(new ItemStack(Items.STATUE_GRANITE));
+		addBlock(list, Blocks.BUTTON_GRANITE);
+		addBlock(list, Blocks.PRESSURE_PLATE_GRANITE);
+		addBlock(list, Blocks.PRESSURE_PLATE_COBBLE_GRANITE);
+		newPage(list);
+
+		addBlock(list, Blocks.PERMAFROST);
+
+		addBlock(list, Blocks.COBBLE_PERMAFROST);
+		addBlock(list, Blocks.STAIRS_COBBLE_PERMAFROST);
+		addBlock(list, Blocks.SLAB_COBBLE_PERMAFROST);
+
+		addBlock(list, Blocks.BRICK_PERMAFROST);
+		addBlock(list, Blocks.STAIRS_BRICK_PERMAFROST);
+		addBlock(list, Blocks.SLAB_BRICK_PERMAFROST);
+
+		addBlock(list, Blocks.PERMAFROST_POLISHED);
+		addBlock(list, Blocks.SLAB_PERMAFROST_POLISHED);
+		list.add(new ItemStack(Items.STATUE_PERMAFROST));
+		addBlock(list, Blocks.BUTTON_PERMAFROST);
+		addBlock(list, Blocks.PRESSURE_PLATE_PERMAFROST);
+		addBlock(list, Blocks.PRESSURE_PLATE_COBBLE_PERMAFROST);
+		newPage(list);
+
+		addBlock(list, Blocks.NETHERRACK);
+
+		addBlock(list, Blocks.COBBLE_NETHERRACK);
+		addBlock(list, Blocks.STAIRS_COBBLE_NETHERRACK);
+		addBlock(list, Blocks.SLAB_COBBLE_NETHERRACK);
+		addBlock(list, Blocks.COBBLE_NETHERRACK_CRYSTALLINE);
+
+		addBlock(list, Blocks.BRICK_NETHERRACK);
+		addBlock(list, Blocks.STAIRS_BRICK_NETHERRACK);
+		addBlock(list, Blocks.SLAB_BRICK_NETHERRACK);
+
+		addBlock(list, Blocks.NETHERRACK_POLISHED);
+		addBlock(list, Blocks.SLAB_NETHERRACK_POLISHED);
+		list.add(new ItemStack(Items.STATUE_NETHERRACK));
+		addBlock(list, Blocks.BUTTON_NETHERRACK);
+		addBlock(list, Blocks.PRESSURE_PLATE_NETHERRACK);
+		addBlock(list, Blocks.PRESSURE_PLATE_COBBLE_NETHERRACK);
+		newPage(list);
+
+		addBlock(list, Blocks.GLOOMSTONE);
+
+		addBlock(list, Blocks.COBBLE_GLOOMSTONE);
+		addBlock(list, Blocks.STAIRS_COBBLE_GLOOMSTONE);
+		addBlock(list, Blocks.SLAB_COBBLE_GLOOMSTONE);
+
+		addBlock(list, Blocks.BRICK_GLOOMSTONE);
+		addBlock(list, Blocks.STAIRS_BRICK_GLOOMSTONE);
+		addBlock(list, Blocks.SLAB_BRICK_GLOOMSTONE);
+
+		addBlock(list, Blocks.GLOOMSTONE_POLISHED);
+		addBlock(list, Blocks.SLAB_GLOOMSTONE_POLISHED);
+		list.add(new ItemStack(Items.STATUE_GLOOMSTONE));
+		addBlock(list, Blocks.BUTTON_GLOOMSTONE);
+		addBlock(list, Blocks.PRESSURE_PLATE_GLOOMSTONE);
+		addBlock(list, Blocks.PRESSURE_PLATE_COBBLE_GLOOMSTONE);
+		newPage(list);
+
+		addBlock(list, Blocks.SANDSTONE);
+		addBlock(list, Blocks.STAIRS_SANDSTONE);
+		addBlock(list, Blocks.SLAB_SANDSTONE);
+		addBlock(list, Blocks.BRICK_SANDSTONE);
+		addBlock(list, Blocks.STAIRS_BRICK_SANDSTONE);
+		addBlock(list, Blocks.SLAB_BRICK_SANDSTONE);
+		addBlock(list, Blocks.BUTTON_SANDSTONE);
+		addBlock(list, Blocks.PRESSURE_PLATE_SANDSTONE);
+		newLine(list);
+
+		addBlock(list, Blocks.BRIMSTONE);
+		addBlock(list, Blocks.STAIRS_BRIMSTONE);
+		addBlock(list, Blocks.SLAB_BRIMSTONE);
+		addBlock(list, Blocks.BRICK_BRIMSTONE);
+		addBlock(list, Blocks.STAIRS_BRICK_BRIMSTONE);
+		addBlock(list, Blocks.SLAB_BRICK_BRIMSTONE);
+		addBlock(list, Blocks.BUTTON_BRIMSTONE);
+		addBlock(list, Blocks.PRESSURE_PLATE_BRIMSTONE);
+		newPage(list);
+
+		addBlock(list, Blocks.MARBLE);
+
+		addBlock(list, Blocks.BRICK_MARBLE);
+		addBlock(list, Blocks.STAIRS_BRICK_MARBLE);
+		addBlock(list, Blocks.SLAB_BRICK_MARBLE);
+
+		addBlock(list, Blocks.PILLAR_MARBLE);
+		addBlock(list, Blocks.CAPSTONE_MARBLE);
+		addBlock(list, Blocks.SLAB_CAPSTONE_MARBLE);
+		list.add(new ItemStack(Items.STATUE_MARBLE));
+		list.add(new ItemStack(Items.STATUE_PIGMAN));
+		newLine(list);
+
+		addBlock(list, Blocks.SLATE);
+		addBlock(list, Blocks.LAYER_SLATE);
+
+		addBlock(list, Blocks.BRICK_SLATE);
+		addBlock(list, Blocks.STAIRS_BRICK_SLATE);
+		addBlock(list, Blocks.SLAB_BRICK_SLATE);
+
+		addBlock(list, Blocks.SLATE_POLISHED);
+		addBlock(list, Blocks.SLAB_SLATE_POLISHED);
+		list.add(new ItemStack(Items.STATUE_SLATE));
+		newPage(list);
+	}
+
+	private static void addLogTypes(List<ItemStack> list) {
+		addBlock(list, Blocks.LOG_OAK);
+		addBlock(list, Blocks.LOG_OAK_MOSSY);
+		addBlock(list, Blocks.LOG_PINE);
+		addBlock(list, Blocks.LOG_BIRCH);
+		addBlock(list, Blocks.LOG_CHERRY);
+		addBlock(list, Blocks.LOG_EUCALYPTUS);
+		addBlock(list, Blocks.LOG_THORN);
+		addBlock(list, Blocks.LOG_PALM);
+		addBlock(list, Blocks.LOG_SCORCHED);
+		newPage(list);
+	}
+
+	private static void addWoodTypes(List<ItemStack> list) {
+		addBlock(list, Blocks.PRESSURE_PLATE_PLANKS_OAK);
+		addBlock(list, Blocks.BUTTON_PLANKS_OAK);
+		addBlock(list, Blocks.PLANKS_OAK);
+		addBlock(list, Blocks.STAIRS_PLANKS_OAK);
+		addBlock(list, Blocks.SLAB_PLANKS_OAK);
+		addBlock(list, Blocks.FENCE_PLANKS_OAK);
+		addBlock(list, Blocks.FENCE_GATE_PLANKS_OAK);
+		addBlock(list, Blocks.TRAPDOOR_PLANKS_OAK);
+		addBlock(list, Blocks.CHEST_PLANKS_OAK);
+		list.add(new ItemStack(Items.DOOR_OAK));
+		list.add(new ItemStack(Items.SIGN));
+	}
+
+	private static void addPaintedTypes(List<ItemStack> list) {
+		for (int i = 0; i < RAINBOW_ORDER.length; i += 2) {
+			addPainted(list, RAINBOW_ORDER[i]);
+            newLine(list);
+            addPainted(list, RAINBOW_ORDER[i + 1]);
+            newPage(list);
+		}
+	}
+
+	private static void addPainted(@NotNull List<ItemStack> list, DyeColor color) {
+		list.add(new ItemStack(Blocks.LAMP_IDLE, 1, painted(Blocks.LAMP_IDLE).toMetadata(color)));
+		addPaintedWoodBlock(list, Blocks.PRESSURE_PLATE_PLANKS_OAK_PAINTED, color);
+		addPaintedWoodBlock(list, Blocks.BUTTON_PLANKS_PAINTED, color);
+		list.add(new ItemStack(Blocks.WOOL, 1, painted(Blocks.WOOL).toMetadata(color)));
+		addPaintedWoodBlock(list, Blocks.PLANKS_OAK_PAINTED, color);
+		addPaintedWoodBlock(list, Blocks.STAIRS_PLANKS_PAINTED, color);
+		addPaintedWoodBlock(list, Blocks.SLAB_PLANKS_PAINTED, color);
+		addPaintedWoodBlock(list, Blocks.FENCE_PLANKS_OAK_PAINTED, color);
+		addPaintedWoodBlock(list, Blocks.FENCE_GATE_PLANKS_OAK_PAINTED, color);
+		addPaintedWoodBlock(list, Blocks.TRAPDOOR_PLANKS_PAINTED, color);
+		addPaintedWoodBlock(list, Blocks.CHEST_PLANKS_OAK_PAINTED, color);
+		list.add(new ItemStack(Items.DOOR_OAK_PAINTED, 1, color.itemMeta));
+		list.add(new ItemStack(Items.SIGN_PAINTED, 1, color.itemMeta));
+	}
+
+	private static void addPaintedWoodBlock(List<ItemStack> list, Block<?> block, DyeColor color) {
+		list.add(new ItemStack(block, 1, painted(block).toMetadata(color)));
+	}
+
+	private static void addDyes(List<ItemStack> list) {
+		for (DyeColor color : RAINBOW_ORDER) {
+			list.add(new ItemStack(Items.DYE, 1, color.itemMeta));
+		}
+	}
+
+	private static void addNaturalTypes(List<ItemStack> list) {
+		addBlock(list, Blocks.GRASS);
+		addBlock(list, Blocks.GRASS_RETRO);
+		addBlock(list, Blocks.DIRT);
+		addBlock(list, Blocks.PATH_DIRT);
+		addBlock(list, Blocks.FARMLAND_DIRT);
+		addBlock(list, Blocks.GRAVEL);
+		newLine(list);
+
+		addBlock(list, Blocks.GRASS_SCORCHED);
+		addBlock(list, Blocks.DIRT_SCORCHED);
+		addBlock(list, Blocks.DIRT_SCORCHED_RICH);
+		addBlock(list, Blocks.MUD);
+		addBlock(list, Blocks.MUD_BAKED);
+		addBlock(list, Blocks.BLOCK_CLAY);
+		newLine(list);
+
+		addBlock(list, Blocks.SAND);
+		addBlock(list, Blocks.BRIMSAND);
+		addBlock(list, Blocks.BRIMTHAW);
+		addBlock(list, Blocks.GLOWSTONE);
+		addBlock(list, Blocks.SULFUR);
+		addBlock(list, Blocks.SULFUR_HARDENED);
+		newLine(list);
+
+		addBlock(list, Blocks.ICE);
+		addBlock(list, Blocks.PERMAICE);
+		addBlock(list, Blocks.BLOCK_SNOW);
+		addBlock(list, Blocks.LAYER_SNOW);
+		addBlock(list, Blocks.BLOCK_ASH);
+		addBlock(list, Blocks.LAYER_ASH);
+		newLine(list);
+
+		addBlock(list, Blocks.BRICK_CLAY);
+		addBlock(list, Blocks.STAIRS_BRICK_CLAY);
+		addBlock(list, Blocks.SLAB_BRICK_CLAY);
+		addBlock(list, Blocks.BONESHALE);
+		addBlock(list, Blocks.BEDROCK);
+		addBlock(list, Blocks.OBSIDIAN);
+		newLine(list);
+
+		addBlock(list, Blocks.MAGMA);
+		addBlock(list, Blocks.SOULSAND);
+		addBlock(list, Blocks.SOULSCHIST);
+		addBlock(list, Blocks.THERMAL_VENT);
+		addBlock(list, Blocks.EMBER);
+		newLine(list);
+	}
+
+	private static void addFood(@NotNull List<ItemStack> list) {
+		list.add(new ItemStack(Items.FOOD_APPLE));
+		list.add(new ItemStack(Items.FOOD_APPLE_GOLD));
+		list.add(new ItemStack(Items.FOOD_CHERRY));
+		list.add(new ItemStack(Items.FOOD_PORKCHOP_RAW));
+		list.add(new ItemStack(Items.FOOD_PORKCHOP_COOKED));
+		list.add(new ItemStack(Items.FOOD_VENISON_RAW));
+		list.add(new ItemStack(Items.FOOD_VENISON_COOKED));
+		list.add(new ItemStack(Items.FOOD_FISH_RAW));
+		list.add(new ItemStack(Items.FOOD_FISH_COOKED));
+		list.add(new ItemStack(Items.DUST_SUGAR));
+		list.add(new ItemStack(Items.EGG_CHICKEN));
+		list.add(new ItemStack(Items.SEEDS_WHEAT));
+		list.add(new ItemStack(Items.SEEDS_PUMPKIN));
+		list.add(new ItemStack(Items.WHEAT));
+		list.add(new ItemStack(Items.DOUGH));
+		list.add(new ItemStack(Items.FOOD_BREAD));
+		list.add(new ItemStack(Items.FOOD_COOKIE));
+		list.add(new ItemStack(Items.FOOD_CAKE));
+		list.add(new ItemStack(Items.FOOD_PUMPKIN_PIE));
+		list.add(new ItemStack(Items.BOWL));
+		list.add(new ItemStack(Items.FOOD_STEW_MUSHROOM));
+	}
+
+	private static void addOrganicTypes(List<ItemStack> list) {
+		addBlock(list, Blocks.LEAVES_OAK);
+		addBlock(list, Blocks.LAYER_LEAVES_OAK);
+		addBlock(list, Blocks.LEAVES_OAK_RETRO);
+		addBlock(list, Blocks.LEAVES_PINE);
+		addBlock(list, Blocks.LEAVES_BIRCH);
+		addBlock(list, Blocks.LEAVES_CHERRY);
+		addBlock(list, Blocks.LEAVES_CHERRY_FLOWERING);
+		addBlock(list, Blocks.LEAVES_EUCALYPTUS);
+		addBlock(list, Blocks.LEAVES_THORN);
+		addBlock(list, Blocks.LEAVES_PALM);
+		addBlock(list, Blocks.LEAVES_SHRUB);
+		addBlock(list, Blocks.LEAVES_CACAO);
+		newLine(list);
+
+		addBlock(list, Blocks.SAPLING_OAK);
+		addBlock(list, Blocks.SAPLING_OAK_RETRO);
+		addBlock(list, Blocks.SAPLING_PINE);
+		addBlock(list, Blocks.SAPLING_BIRCH);
+		addBlock(list, Blocks.SAPLING_CHERRY);
+		addBlock(list, Blocks.SAPLING_EUCALYPTUS);
+		addBlock(list, Blocks.SAPLING_THORN);
+		addBlock(list, Blocks.SAPLING_PALM);
+		addBlock(list, Blocks.SAPLING_SHRUB);
+		addBlock(list, Blocks.SAPLING_CACAO);
+		newLine(list);
+
+		list.add(new ItemStack(Blocks.FLOWER_YELLOW, 1, 0));
+		list.add(new ItemStack(Blocks.FLOWER_RED, 1, 0));
+		list.add(new ItemStack(Blocks.FLOWER_PINK, 1, 0));
+		list.add(new ItemStack(Blocks.FLOWER_PURPLE, 1, 0));
+		list.add(new ItemStack(Blocks.FLOWER_LIGHT_BLUE, 1, 0));
+		list.add(new ItemStack(Blocks.FLOWER_ORANGE, 1, 0));
+
+		addBlock(list, Blocks.MUSHROOM_BROWN);
+		addBlock(list, Blocks.MUSHROOM_RED);
+		newLine(list);
+
+		addBlock(list, Blocks.TALLGRASS);
+		addBlock(list, Blocks.TALLGRASS_FERN);
+		addBlock(list, Blocks.DEADBUSH);
+		addBlock(list, Blocks.SPINIFEX);
+		addBlock(list, Blocks.ALGAE);
+		addBlock(list, Blocks.CACTUS);
+		newLine(list);
+
+		addBlock(list, Blocks.COBWEB);
+		addBlock(list, Blocks.BONE_PILE);
+		addBlock(list, Blocks.SOUL_CATCHER);
+		addBlock(list, Blocks.BOULDER_MAGMATIC);
+		addBlock(list, Blocks.BOULDER_SULFURIC);
+		newLine(list);
+
+		addBlock(list, Blocks.PUMPKIN);
+		addBlock(list, Blocks.PUMPKIN_CARVED_IDLE);
+		addBlock(list, Blocks.PUMPKIN_CARVED_ACTIVE);
+
+		addBlock(list, Blocks.BLOCK_SUGARCANE);
+		addBlock(list, Blocks.BLOCK_SUGARCANE_BAKED);
+		newLine(list);
+
+		addBlock(list, Blocks.SPONGE_DRY);
+		addBlock(list, Blocks.SPONGE_WET);
+
+		addBlock(list, Blocks.PUMICE_DRY);
+		addBlock(list, Blocks.PUMICE_WET);
+		newLine(list);
+	}
+
+	private static void addWorkstationsAndGlass(List<ItemStack> list) {
+		addBlock(list, Blocks.WORKBENCH);
+		addBlock(list, Blocks.FURNACE_STONE_IDLE);
+		addBlock(list, Blocks.FURNACE_BLAST_IDLE);
+		addBlock(list, Blocks.TROMMEL_IDLE);
+		addBlock(list, Blocks.BOOKSHELF_PLANKS_OAK);
+		addBlock(list, Blocks.LADDER_OAK);
+		addBlock(list, Blocks.TORCH_COAL);
+		addBlock(list, Blocks.GLASS);
+		addBlock(list, Blocks.TRAPDOOR_GLASS);
+		addBlock(list, Blocks.GLASS_TINTED);
+		addBlock(list, Blocks.GLASS_STEEL);
+	}
+
+	private static void addArmor(@NotNull List<ItemStack> list) {
+		list.add(new ItemStack(Items.ARMOR_HELMET_LEATHER));
+		list.add(new ItemStack(Items.ARMOR_CHESTPLATE_LEATHER));
+		list.add(new ItemStack(Items.ARMOR_LEGGINGS_LEATHER));
+		list.add(new ItemStack(Items.ARMOR_BOOTS_LEATHER));
+		list.add(new ItemStack(Items.ARMOR_WOLF_LEATHER));
+		list.add(new ItemStack(Items.ARMOR_QUIVER));
+		newLine(list);
+
+		list.add(new ItemStack(Items.ARMOR_HELMET_CHAINMAIL));
+		list.add(new ItemStack(Items.ARMOR_CHESTPLATE_CHAINMAIL));
+		list.add(new ItemStack(Items.ARMOR_LEGGINGS_CHAINMAIL));
+		list.add(new ItemStack(Items.ARMOR_BOOTS_CHAINMAIL));
+		list.add(new ItemStack(Items.ARMOR_WOLF_CHAINMAIL));
+		list.add(new ItemStack(Items.ARMOR_QUIVER_GOLD));
+		newLine(list);
+
+		list.add(new ItemStack(Items.ARMOR_HELMET_IRON));
+		list.add(new ItemStack(Items.ARMOR_CHESTPLATE_IRON));
+		list.add(new ItemStack(Items.ARMOR_LEGGINGS_IRON));
+		list.add(new ItemStack(Items.ARMOR_BOOTS_IRON));
+		list.add(new ItemStack(Items.ARMOR_WOLF_IRON));
+		list.add(new ItemStack(Items.ARMOR_BOOTS_ICESKATES));
+		newLine(list);
+
+		list.add(new ItemStack(Items.ARMOR_HELMET_GOLD));
+		list.add(new ItemStack(Items.ARMOR_CHESTPLATE_GOLD));
+		list.add(new ItemStack(Items.ARMOR_LEGGINGS_GOLD));
+		list.add(new ItemStack(Items.ARMOR_BOOTS_GOLD));
+		list.add(new ItemStack(Items.ARMOR_WOLF_GOLD));
+		newLine(list);
+
+		list.add(new ItemStack(Items.ARMOR_HELMET_DIAMOND));
+		list.add(new ItemStack(Items.ARMOR_CHESTPLATE_DIAMOND));
+		list.add(new ItemStack(Items.ARMOR_LEGGINGS_DIAMOND));
+		list.add(new ItemStack(Items.ARMOR_BOOTS_DIAMOND));
+		list.add(new ItemStack(Items.ARMOR_WOLF_DIAMOND));
+		newLine(list);
+
+		list.add(new ItemStack(Items.ARMOR_HELMET_STEEL));
+		list.add(new ItemStack(Items.ARMOR_CHESTPLATE_STEEL));
+		list.add(new ItemStack(Items.ARMOR_LEGGINGS_STEEL));
+		list.add(new ItemStack(Items.ARMOR_BOOTS_STEEL));
+		list.add(new ItemStack(Items.ARMOR_WOLF_STEEL));
+		newLine(list);
+
+
+
+
+		newLine(list);
+
+
+	}
+
+	private static void addRedstoneTypes(List<ItemStack> list) {
+		addBlock(list, Blocks.BLOCK_REDSTONE);
+		list.add(new ItemStack(Items.DUST_REDSTONE));
+		list.add(new ItemStack(Items.REPEATER));
+		list.add(new ItemStack(Items.TIMER));
+		addBlock(list, Blocks.TORCH_REDSTONE_ACTIVE);
+		addBlock(list, Blocks.LEVER_COBBLE_STONE);
+
+		addBlock(list, Blocks.PUMPKIN_REDSTONE);
+		addBlock(list, Blocks.PISTON_BASE);
+		addBlock(list, Blocks.PISTON_BASE_STICKY);
+		addBlock(list, Blocks.PISTON_BASE_STEEL);
+		addBlock(list, Blocks.DISPENSER_COBBLE_STONE);
+		addBlock(list, Blocks.MOTION_SENSOR_IDLE);
+		newLine(list);
+
+		addBlock(list, Blocks.ACTIVATOR);
+		addBlock(list, Blocks.MATCHER);
+		addBlock(list, Blocks.CONDUIT);
+		addBlock(list, Blocks.RUBYGLASS_COLUMN);
+		addBlock(list, Blocks.RUBYGLASS_NODE);
+		addBlock(list, Blocks.BLOCK_RUBYGLASS);
+		addBlock(list, Blocks.RUBYGLASS_GROWTH);
+		addBlock(list, Blocks.RUBYGLASS_CRYSTAL);
+		addBlock(list, Blocks.MESH);
+		addBlock(list, Blocks.MESH_GOLD);
+		addBlock(list, Blocks.MOBSPAWNER);
+		addBlock(list, Blocks.MOBSPAWNER_DEACTIVATED);
+		addBlock(list, Blocks.RAIL);
+		addBlock(list, Blocks.RAIL_POWERED);
+		addBlock(list, Blocks.RAIL_DETECTOR);
+		list.add(new ItemStack(Items.MINECART));
+		list.add(new ItemStack(Items.MINECART_CHEST));
+		list.add(new ItemStack(Items.MINECART_FURNACE));
+		list.add(new ItemStack(Items.SADDLE));
+		list.add(new ItemStack(Items.BOAT));
+		addBlock(list, Blocks.NOTEBLOCK);
+		addBlock(list, Blocks.JUKEBOX);
+		addBlock(list, Blocks.TNT);
+		addBlock(list, Blocks.SPIKES);
+		newLine(list);
+	}
+
+	private static void addOreTypes(List<ItemStack> list) {
+		addBlock(list, Blocks.ORE_COAL_STONE);
+		addBlock(list, Blocks.ORE_COAL_BASALT);
+		addBlock(list, Blocks.ORE_COAL_LIMESTONE);
+		addBlock(list, Blocks.ORE_COAL_GRANITE);
+		addBlock(list, Blocks.ORE_COAL_PERMAFROST);
+		newLine(list);
+
+		addBlock(list, Blocks.ORE_IRON_STONE);
+		addBlock(list, Blocks.ORE_IRON_BASALT);
+		addBlock(list, Blocks.ORE_IRON_LIMESTONE);
+		addBlock(list, Blocks.ORE_IRON_GRANITE);
+		addBlock(list, Blocks.ORE_IRON_PERMAFROST);
+		newLine(list);
+
+		addBlock(list, Blocks.ORE_GOLD_STONE);
+		addBlock(list, Blocks.ORE_GOLD_BASALT);
+		addBlock(list, Blocks.ORE_GOLD_LIMESTONE);
+		addBlock(list, Blocks.ORE_GOLD_GRANITE);
+		addBlock(list, Blocks.ORE_GOLD_PERMAFROST);
+		newLine(list);
+
+		addBlock(list, Blocks.ORE_LAPIS_STONE);
+		addBlock(list, Blocks.ORE_LAPIS_BASALT);
+		addBlock(list, Blocks.ORE_LAPIS_LIMESTONE);
+		addBlock(list, Blocks.ORE_LAPIS_GRANITE);
+		addBlock(list, Blocks.ORE_LAPIS_PERMAFROST);
+
+		addBlock(list, Blocks.ORE_NETHERCOAL_BASALT);
+		newLine(list);
+
+		addBlock(list, Blocks.ORE_REDSTONE_STONE);
+		addBlock(list, Blocks.ORE_REDSTONE_BASALT);
+		addBlock(list, Blocks.ORE_REDSTONE_LIMESTONE);
+		addBlock(list, Blocks.ORE_REDSTONE_GRANITE);
+		addBlock(list, Blocks.ORE_REDSTONE_PERMAFROST);
+
+		addBlock(list, Blocks.ORE_NETHERCOAL_NETHERRACK);
+		newLine(list);
+
+		addBlock(list, Blocks.ORE_DIAMOND_STONE);
+		addBlock(list, Blocks.ORE_DIAMOND_BASALT);
+		addBlock(list, Blocks.ORE_DIAMOND_LIMESTONE);
+		addBlock(list, Blocks.ORE_DIAMOND_GRANITE);
+		addBlock(list, Blocks.ORE_DIAMOND_PERMAFROST);
+
+		addBlock(list, Blocks.ORE_NETHERCOAL_GLOOMSTONE);
+		newLine(list);
+
+
+
+
+	}
+
+	private static void addOreProducts(@NotNull List<ItemStack> list) {
+		list.add(new ItemStack(Items.AMMO_PEBBLE));
+		list.add(new ItemStack(Items.COAL));
+		list.add(new ItemStack(Items.COAL, 1, 1));
+		list.add(new ItemStack(Items.NETHERCOAL));
+		list.add(new ItemStack(Items.OLIVINE));
+		list.add(new ItemStack(Items.ORE_RAW_IRON));
+		list.add(new ItemStack(Items.INGOT_IRON));
+		list.add(new ItemStack(Items.ORE_RAW_GOLD));
+		list.add(new ItemStack(Items.INGOT_GOLD));
+		list.add(new ItemStack(Items.INGOT_STEEL_CRUDE));
+		list.add(new ItemStack(Items.INGOT_STEEL));
+		list.add(new ItemStack(Items.QUARTZ));
+		list.add(new ItemStack(Items.RUBYGLASS));
+		list.add(new ItemStack(Items.DIAMOND));
+		list.add(new ItemStack(Items.FLINT));
+		list.add(new ItemStack(Items.CLAY));
+		list.add(new ItemStack(Items.BRICK_CLAY));
+		list.add(new ItemStack(Items.SULFUR));
+		list.add(new ItemStack(Items.DUST_GLOWSTONE));
+	}
+
+	private static void addStorageTypes(List<ItemStack> list) {
+		addBlock(list, Blocks.BLOCK_IRON);
+		addBlock(list, Blocks.BLOCK_STEEL);
+		addBlock(list, Blocks.BLOCK_GOLD);
+		addBlock(list, Blocks.BLOCK_LAPIS);
+		addBlock(list, Blocks.BLOCK_DIAMOND);
+		addBlock(list, Blocks.BLOCK_QUARTZ);
+		addBlock(list, Blocks.BLOCK_COAL);
+		addBlock(list, Blocks.BLOCK_CHARCOAL);
+		addBlock(list, Blocks.BLOCK_NETHER_COAL);
+		addBlock(list, Blocks.BLOCK_OLIVINE);
+		newLine(list);
+
+		addBlock(list, Blocks.BRICK_IRON);
+		addBlock(list, Blocks.STAIRS_BRICK_IRON);
+		addBlock(list, Blocks.SLAB_BRICK_IRON);
+		addBlock(list, Blocks.BRICK_GOLD);
+		addBlock(list, Blocks.STAIRS_BRICK_GOLD);
+		addBlock(list, Blocks.SLAB_BRICK_GOLD);
+		newLine(list);
+
+		addBlock(list, Blocks.BRICK_DIAMOND);
+		addBlock(list, Blocks.STAIRS_BRICK_DIAMOND);
+		addBlock(list, Blocks.SLAB_BRICK_DIAMOND);
+		addBlock(list, Blocks.BRICK_STEEL);
+		addBlock(list, Blocks.STAIRS_BRICK_STEEL);
+		addBlock(list, Blocks.SLAB_BRICK_STEEL);
+		newLine(list);
+
+		addBlock(list, Blocks.BRICK_QUARTZ);
+		addBlock(list, Blocks.STAIRS_BRICK_QUARTZ);
+		addBlock(list, Blocks.SLAB_BRICK_QUARTZ);
+		addBlock(list, Blocks.BRICK_LAPIS);
+		addBlock(list, Blocks.STAIRS_BRICK_LAPIS);
+		addBlock(list, Blocks.SLAB_BRICK_LAPIS);
+		newLine(list);
+
+		addBlock(list, Blocks.BRICK_OLIVINE);
+		addBlock(list, Blocks.STAIRS_BRICK_OLIVINE);
+		addBlock(list, Blocks.SLAB_BRICK_OLIVINE);
+		addBlock(list, Blocks.BRICK_RUBYGLASS);
+		addBlock(list, Blocks.STAIRS_BRICK_RUBYGLASS);
+		addBlock(list, Blocks.SLAB_BRICK_RUBYGLASS);
+		newLine(list);
+
+	}
+
+	private static void addBasics(@NotNull List<ItemStack> list) {
+		list.add(new ItemStack(Items.STICK));
+		list.add(new ItemStack(Items.AMMO_SNOWBALL));
+		list.add(new ItemStack(Items.SUGARCANE));
+		list.add(new ItemStack(Items.PAPER));
+		list.add(new ItemStack(Items.BOOK));
+	}
+
+	private static void addMobDrops(@NotNull List<ItemStack> list) {
+		list.add(new ItemStack(Items.CLOTH));
+		list.add(new ItemStack(Items.STRING));
+		list.add(new ItemStack(Items.FEATHER_CHICKEN));
+		list.add(new ItemStack(Items.GUNPOWDER));
+		list.add(new ItemStack(Items.BONE));
+		list.add(new ItemStack(Items.CHAINLINK));
+		list.add(new ItemStack(Items.SLIMEBALL));
+		list.add(new ItemStack(Items.LEATHER));
+	}
+
+	private static void addPlaceables(List<ItemStack> list) {
+		addBlock(list, Blocks.PAPER_WALL);
+		addBlock(list, Blocks.FENCE_PAPER_WALL);
+
+		addBlock(list, Blocks.FENCE_CHAINLINK);
+		addBlock(list, Blocks.FENCE_STEEL);
+
+		list.add(new ItemStack(Items.PAINTING));
+		newLine(list);
+
+		list.add(new ItemStack(Items.DOOR_GLASS));
+		list.add(new ItemStack(Items.DOOR_IRON));
+		list.add(new ItemStack(Items.DOOR_STEEL));
+		addBlock(list, Blocks.TRAPDOOR_IRON);
+		addBlock(list, Blocks.TRAPDOOR_STEEL);
+		newLine(list);
+
+		list.add(new ItemStack(Items.FLAG));
+		list.add(new ItemStack(Items.BED));
+		list.add(new ItemStack(Items.SEAT));
+		addBlock(list, Blocks.BRAZIER_INACTIVE);
+		list.add(new ItemStack(Items.BASKET));
+		list.add(new ItemStack(Items.JAR));
+		newLine(list);
+
+		list.add(new ItemStack(Items.LANTERN_FIREFLY_GREEN));
+		list.add(new ItemStack(Items.LANTERN_FIREFLY_BLUE));
+		list.add(new ItemStack(Items.LANTERN_FIREFLY_ORANGE));
+		list.add(new ItemStack(Items.LANTERN_FIREFLY_RED));
+		newLine(list);
+
+		list.add(new ItemStack(Items.JAR_BUTTERFLY_BLUE));
+		list.add(new ItemStack(Items.JAR_BUTTERFLY_ORANGE));
+		list.add(new ItemStack(Items.JAR_BUTTERFLY_PINK));
+		list.add(new ItemStack(Items.JAR_BUTTERFLY_SILVER));
+	}
+
+	private static void addRecords(@NotNull List<ItemStack> list) {
+		list.add(new ItemStack(Items.RECORD_13));
+		list.add(new ItemStack(Items.RECORD_CAT));
+		list.add(new ItemStack(Items.RECORD_BLOCKS));
+		list.add(new ItemStack(Items.RECORD_CHIRP));
+		list.add(new ItemStack(Items.RECORD_FAR));
+		list.add(new ItemStack(Items.RECORD_MALL));
+		list.add(new ItemStack(Items.RECORD_MELLOHI));
+		list.add(new ItemStack(Items.RECORD_STAL));
+		list.add(new ItemStack(Items.RECORD_STRAD));
+		list.add(new ItemStack(Items.RECORD_WARD));
+		list.add(new ItemStack(Items.RECORD_WAIT));
+		list.add(new ItemStack(Items.RECORD_DOG));
+	}
+
+	private static void addBucketVariants(List<ItemStack> list, Item item) {
+		if (item instanceof ItemBucket itemBucket) {
+			list.add(new ItemStack(item));
+			for (NamespaceID stateId : ItemBucket.getRegisteredStateIds()) {
+				if (!ItemBucket.STATE_EMPTY.equals(stateId)) {
+					ItemStack itemStack = new ItemStack(item, 1);
+					ItemBucket.setState(itemStack, stateId);
+					ItemBucket.setCharges(itemStack, itemBucket.maxCharges);
+					list.add(itemStack);
+				}
+			}
+		}
+	}
+
+	private static void addBlock(List<ItemStack> list, Block<?> @NotNull ... blocks) {
+		for (Block<?> block : blocks) {
+			list.add(new ItemStack(block));
+		}
+	}
+
+	private static @NotNull IPainted painted(@NotNull Block<?> block) {
+		return (IPainted) block.getLogic();
+	}
+}
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java
index 75b22c5cf..d28f2b8f8 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java
@@ -1,24 +1,20 @@
 package net.minecraft.core.player.inventory.menu;
 
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.IPainted;
-import net.minecraft.core.block.tag.BlockTags;
-import net.minecraft.core.item.*;
-import net.minecraft.core.item.tag.ItemTags;
+import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.lang.I18n;
-import net.minecraft.core.block.Blocks;
-import net.minecraft.core.player.inventory.CreativeBlocks;
-import net.minecraft.core.player.inventory.CreativeItems;
+import net.minecraft.core.player.inventory.CreativeMenuContents;
 import net.minecraft.core.player.inventory.container.ContainerInventory;
 import net.minecraft.core.player.inventory.slot.SlotCreative;
-import net.minecraft.core.util.collection.NamespaceID;
-import net.minecraft.core.util.helper.DyeColor;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 public class MenuInventoryCreative extends MenuInventory
 {
+	public static final int CREATIVE_COLUMNS = 6;
+	public static final int CREATIVE_PAGE_SIZE = CREATIVE_COLUMNS * CREATIVE_COLUMNS;
+
 	public int page = 0;
 	public int maxPage;
 	protected int creativeSlotsStart;
@@ -32,29 +28,28 @@ public class MenuInventoryCreative extends MenuInventory
 		creativeSlotsStart = this.slots.size();
 		
 		// Add creative slots
-		for (int i = 0; i < 36; i++)
+		for (int i = 0; i < CREATIVE_PAGE_SIZE; i++)
 		{
 			int x = i % 6;
 			int y = i / 6;
 			
-			addSlot(new SlotCreative(creativeSlotsStart + i, 184 + (x * 18), 30 + (y * 18), creativeItems.get(i)));
+			addSlot(new SlotCreative(creativeSlotsStart + i, 184 + (x * 18), 30 + (y * 18), creativeContents.get(i)));
 		}
 		
 		searchPage("");
 	}
-	
+
 	public void setInventoryStatus(int page, String searchText)
 	{
-		if (this.page != page)
-		{
+		String incoming = searchText == null ? "" : searchText;
+		if (!Objects.equals(this.searchText, incoming)) {
+			searchPage(incoming);
+			return;
+		}
+		if (this.page != page) {
 			this.page = page;
 			updatePage();
 		}
-		if (!this.searchText.equals(searchText))
-		{
-			this.searchText = searchText;
-			searchPage(searchText);
-		}
 	}
 	
 	public void lastPage()
@@ -65,51 +60,98 @@ public class MenuInventoryCreative extends MenuInventory
 		updatePage();
 	}
 	
+	/**
+	 * Advances one full page. {@link #searchedItems} is padded with trailing {@code null}
+	 * entries (in {@link #updatePage}) so the list length is always a multiple of {@link #CREATIVE_PAGE_SIZE},
+	 * keeping each page aligned to the grid.
+	 */
 	public void nextPage()
 	{
 		if (page == maxPage) return;
-		
+
 		page++;
 		updatePage();
 	}
+
+	public void jumpToFirstCreativePage() {
+		if (this.page <= 0) {
+			return;
+		}
+		this.page = 0;
+		this.updatePage();
+	}
+
+	public void jumpToLastCreativePage() {
+		if (this.page >= this.maxPage) {
+			return;
+		}
+		this.page = this.maxPage;
+		this.updatePage();
+	}
 	
 	public void searchPage(String search)
 	{
-		searchText = search;
-		searchedItems.clear();
-		page = 0;
-		I18n t = I18n.getInstance();
+		if (search == null) {
+			search = "";
+		}
+		this.searchText = search;
+		this.page = 0;
+		this.refillSearchedItemsMatchingCurrentQuery();
+		this.updatePage();
+	}
 
-		int itemsCount = creativeItems.size();
-		for (int i = 0; i < itemsCount; i++)
-		{
-			if (t.translateKey(creativeItems.get(i).getItemKey() + ".name").toLowerCase().contains(search.toLowerCase()))
-			{
-				searchedItems.add(creativeItems.get(i));
+	private void refillSearchedItemsMatchingCurrentQuery() {
+		this.searchedItems.clear();
+		final I18n t = I18n.getInstance();
+		final String needle = this.searchText.toLowerCase();
+		final int itemsCount = creativeContents.size();
+		for (int i = 0; i < itemsCount; i++) {
+			final ItemStack stack = creativeContents.get(i);
+			if (stack == null) {
+				if (this.searchText.isEmpty()) {
+					this.searchedItems.add(null);
+				}
+				continue;
+			}
+			if (t.translateKey(stack.getItemKey() + ".name").toLowerCase().contains(needle)) {
+				this.searchedItems.add(stack);
 			}
 		}
-		
-		updatePage();
 	}
 	
 	protected void updatePage()
 	{
-		maxPage = searchedItems.size() / 36;
-		if (searchedItems.size() % 36 == 0) maxPage--;
+		int n = searchedItems.size();
+		if (n > 0) {
+			int rem = n % CREATIVE_PAGE_SIZE;
+			if (rem != 0) {
+				for (int pad = 0; pad < CREATIVE_PAGE_SIZE - rem; pad++) {
+					searchedItems.add(null);
+				}
+			}
+		}
+
+		n = searchedItems.size();
+		maxPage = n / CREATIVE_PAGE_SIZE;
+		if (n % CREATIVE_PAGE_SIZE == 0) maxPage--;
 		if (maxPage == -1) maxPage = 0;
-		
-		for (int i = 0; i < 36; i++)
+		if (page > maxPage) {
+			page = maxPage;
+		}
+
+		for (int i = 0; i < CREATIVE_PAGE_SIZE; i++)
 		{
-			if (i + (page * 36) >= searchedItems.size())
+			int idx = i + page * CREATIVE_PAGE_SIZE;
+			if (idx >= n)
 			{
 				((SlotCreative)this.slots.get(creativeSlotsStart + i)).item = null;
 			}
 			else
 			{
-				((SlotCreative)this.slots.get(creativeSlotsStart + i)).item = searchedItems.get(i + (page * 36));
-			}			
+				((SlotCreative)this.slots.get(creativeSlotsStart + i)).item = searchedItems.get(idx);
+			}
 		}
-		
+
 		inventory.player.updateCreativeInventory(page, searchText);
 	}
 
@@ -122,59 +164,9 @@ public class MenuInventoryCreative extends MenuInventory
 		return number + 8 + 27;
 	}
 	
-	public static List<ItemStack> creativeItems = new ArrayList<>();
+	public static List<ItemStack> creativeContents = new ArrayList<>();
 
-	static
-	{
-		CreativeBlocks.populate(creativeItems);
-		CreativeItems.populate(creativeItems);
+	static {
+		CreativeMenuContents.populate(creativeContents);
 	}
-
-	// PREVIOUS IMPLEMENTATION:
-
-		/*for (Block<?> block : Blocks.blocksList) {
-			if (block == null || block.hasTag(BlockTags.NOT_IN_CREATIVE_MENU)) continue;
-
-			if (Block.hasLogicClass(block, IPainted.class)) {
-				IPainted painted = (IPainted) block.getLogic();
-				for (DyeColor color : DyeColor.values()) {
-					creativeItems.add(new ItemStack(block, 1, painted.toMetadata(color)));
-				}
-			} else if (block == Blocks.FLOWSTONE) {
-				for (int i = 0; i < 4; i++) {
-					creativeItems.add(new ItemStack(block, 1, i));
-				}
-			} else {
-				creativeItems.add(new ItemStack(block));
-			}
-		}
-		
-		for (int i = Blocks.blocksList.length; i < Item.itemsList.length; i++)
-		{
-			Item item = Item.itemsList[i];
-			if (item == null || item.hasTag(ItemTags.NOT_IN_CREATIVE_MENU)) continue;
-			if (item == Items.PAINTBRUSH) {
-				creativeItems.add(new ItemStack(item, 1, Items.PAINTBRUSH.getMaxDamage()));
-			} else if (item == Items.COAL) {
-				creativeItems.add(new ItemStack(item, 1, ItemCoal.META_COAL));
-				creativeItems.add(new ItemStack(item, 1, ItemCoal.META_CHARCOAL));
-			} else if (item == Items.DYE || item == Items.DOOR_OAK_PAINTED || item == Items.SIGN_PAINTED) {
-				for (DyeColor color : DyeColor.values()) {
-					creativeItems.add(new ItemStack(item, 1, color.itemMeta));
-				}
-           } else if (item instanceof ItemBucket bucket) {
-				creativeItems.add(new ItemStack(item));
-				for (NamespaceID stateId : ItemBucket.getRegisteredStateIds()) {
-					if (ItemBucket.STATE_EMPTY.equals(stateId)) continue;
-					ItemStack itemStack = new ItemStack(item, 1);
-					ItemBucket.setState(itemStack, stateId);
-					ItemBucket.setCharges(itemStack, bucket.maxCharges);
-
-					creativeItems.add(itemStack);
-				}
-			} else {
-				creativeItems.add(new ItemStack(item));
-			}
-		}
-	}*/
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java
index bc07f6874..efa7e670d 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java
@@ -11,6 +11,10 @@ import net.minecraft.core.world.biome.Biomes;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.world.generate.chunk.*;
 import net.minecraft.core.world.generate.feature.*;
+import net.minecraft.core.world.generate.feature.WorldFeatureNetherScatterBonePile;
+import net.minecraft.core.world.generate.feature.WorldFeatureNetherScatterBoulderMagmatic;
+import net.minecraft.core.world.generate.feature.WorldFeatureNetherScatterBoulderSulfuric;
+import net.minecraft.core.world.generate.feature.WorldFeatureNetherScatterEmberAsh;
 import net.minecraft.core.world.noise.FractalNoise2D;
 import net.minecraft.core.world.noise.ImprovedPerlinNoise;
 import net.minecraft.core.world.noise.WorleyNoise;
@@ -266,13 +270,32 @@ public class ChunkDecoratorNether
                 .withPositionSelector(PositionSelectors.HeightRangeUniformFromOcean)
                 .withPlacementMethod(new PlacementMethod.TriesPerChunk(32)));
 
-        this.register("minecraft:decoration/nether/default/scatter", (new ChunkDecorationBuilder(new WorldFeatureNetherScatter()))
+        this.register("minecraft:decoration/nether/default/scatter_ember_ash", (new ChunkDecorationBuilder(new WorldFeatureNetherScatterEmberAsh()))
                 .withPositionSelector(PositionSelectors.HeightRangeUniformFromOcean)
-                .withPlacementMethod(new PlacementMethod.TriesPerChunk(32)));
+                .withPlacementMethod(new PlacementMethod.TriesPerChunk(20)));
+
+        this.register("minecraft:decoration/nether/default/scatter_bone_pile", (new ChunkDecorationBuilder(new WorldFeatureNetherScatterBonePile()))
+                .withPositionSelector(PositionSelectors.HeightRangeUniformFromOcean)
+                .withPlacementMethod(new PlacementMethod.TriesPerChunk(8)));
+
+        this.register("minecraft:decoration/nether/default/scatter_boulder_magmatic", (new ChunkDecorationBuilder(new WorldFeatureNetherScatterBoulderMagmatic()))
+                .withBiomeMask(new Biome[]{Biomes.NETHER_CRAG, Biomes.NETHER_SHELF, Biomes.NETHER_VOLCANIC_ISLANDS})
+                .withPositionSelector(PositionSelectors.HeightRangeUniformFromOcean)
+                .withPlacementMethod(new PlacementMethod.TriesPerChunk(8)));
+
+        this.register("minecraft:decoration/nether/default/scatter_boulder_magmatic_sparce", (new ChunkDecorationBuilder(new WorldFeatureNetherScatterBoulderMagmatic()))
+                .withBiomeMask(new Biome[]{Biomes.NETHER_CRYSTAL_FOREST, Biomes.NETHER_CRYSTAL_PLAINS})
+                .withPositionSelector(PositionSelectors.HeightRangeUniformFromOcean)
+                .withPlacementMethod(new PlacementMethod.TriesPerChunk(4)));
+
+        this.register("minecraft:decoration/nether/default/scatter_boulder_sulfuric", (new ChunkDecorationBuilder(new WorldFeatureNetherScatterBoulderSulfuric()))
+                .withBiomeMask(new Biome[]{Biomes.NETHER_SULFUR_POOLS})
+                .withPositionSelector(PositionSelectors.HeightRangeUniformFromOcean)
+                .withPlacementMethod(new PlacementMethod.TriesPerChunk(24)));
 
         this.register("minecraft:decoration/nether/default/patch_soul_catcher", (new ChunkDecorationBuilder(new WorldFeatureSoulCatcherPatch()))
                 .withPositionSelector(PositionSelectors.HeightRangeUniformFromOcean)
-                .withPlacementMethod(new PlacementMethod.TriesPerChunk(2)));
+                .withPlacementMethod(new PlacementMethod.TriesPerChunk(8)));
 
         this.register("minecraft:decoration/nether/default/pebbles", (world, chunk, worldX, worldZ, minY, maxY, rangeY, rand) -> {
             for (int i = 0; i < 16; ++i) {
@@ -305,7 +328,7 @@ public class ChunkDecoratorNether
                     if (world.isAirBlock(queryPose)) {
                         Block<?> blockBelow = world.getBlock(dx, dy - 1, dz);
 
-                        if (blockBelow != Blocks.OBSIDIAN && blockBelow.getMaterial().blocksMotion()
+                        if (blockBelow != Blocks.OBSIDIAN && blockBelow != Blocks.SOULSAND && blockBelow.getMaterial().blocksMotion()
                                 && !isRubyglassAshSupportForbidden(blockBelow)) {
 
                             Biome localBiome = world.getBlockBiome(queryPose);
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java
index 9f48d9c37..80c28a081 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java
@@ -165,16 +165,16 @@ public class SurfaceGeneratorNether implements SurfaceGenerator {
                         currentLayerDepth = soilThickness + 2;
 
                         if (y >= absoluteOceanY - 1) {
-                            result.setBlock(x, y, z, topBlock);
+                            result.setBlock(x, y, z, this.cragOrShelfFloorMixIfCobble(biome, topBlock, rand));
                         } else {
                             // if the block is below ocean level, set it to the chosen filler block
-                            result.setBlock(x, y, z, fillerBlock);
+                            result.setBlock(x, y, z, this.cragOrShelfFloorMixIfCobble(biome, fillerBlock, rand));
                         }
                         continue;
                     }
 
                     if (currentLayerDepth > 0) {
-                        result.setBlock(x, y, z, fillerBlock);
+                        result.setBlock(x, y, z, this.cragOrShelfFloorMixIfCobble(biome, fillerBlock, rand));
                         currentLayerDepth--;
                     }
 
@@ -196,6 +196,13 @@ public class SurfaceGeneratorNether implements SurfaceGenerator {
         }
     }
 
+    private short cragOrShelfFloorMixIfCobble(final @NotNull Biome biome, final short blockId, final @NotNull Random rand) {
+        if ((biome != Biomes.NETHER_CRAG && biome != Biomes.NETHER_SHELF) || blockId != this.cobbleNetherrackId) {
+            return blockId;
+        }
+        return (short) (rand.nextInt(2) == 0 ? this.netherrackId : this.cobbleNetherrackId);
+    }
+
     private int computeBiomeStoneBlock(Biome biome, int worldFillBlock) {
         if (biome == Biomes.NETHER_VOLCANIC_ISLANDS) {
             return brimsandId;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java
index 08ede7be9..06ac14c92 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/ChunkDecoratorOverworld.java
@@ -710,7 +710,9 @@ public class ChunkDecoratorOverworld
 
         final boolean wantsSnow = localBiome.hasTag(BiomeTags.HAS_SURFACE_SNOW) || this.world.getWorldType().hasTag(WorldTypeTags.ENDLESS_SNOW);
         if (wantsSnow && dy > 0 && dy < this.world.getHeightBlocks()) {
-            if (this.world.isAirBlock(dx, dy, dz) && this.world.getBlockMaterial(dx, dy - 1, dz).blocksMotion()) {
+            if (this.world.isAirBlock(dx, dy, dz)
+                    && this.world.getBlockMaterial(dx, dy - 1, dz).blocksMotion()
+                    && this.world.getBlockMaterial(dx, dy - 1, dz) != Materials.ICE) {
                 this.world.setBlockWithNotify(dx, dy, dz, Blocks.LAYER_SNOW.id());
             }
             final int minScanY = Math.max(1, dy - 32);
@@ -737,7 +739,7 @@ public class ChunkDecoratorOverworld
                         continue;
                     }
                     if (below.getMaterial() == Materials.WOOD) { continue; }
-                    if (below.getMaterial().blocksMotion()) {
+                    if (below.getMaterial().blocksMotion() && below.getMaterial() != Materials.ICE) {
                         this.world.setBlockWithNotify(dx, scanY, dz, Blocks.LAYER_SNOW.id());
                         break;
                     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/ChunkDecoratorOverworldB173.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/ChunkDecoratorOverworldB173.java
index d518830a0..9bb496bd1 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/ChunkDecoratorOverworldB173.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/ChunkDecoratorOverworldB173.java
@@ -375,7 +375,9 @@ public class ChunkDecoratorOverworldB173
         final Biome localBiome = this.world.getBlockBiome(xx, yy, zz);
 
         if (localBiome.hasTag(BiomeTags.HAS_SURFACE_SNOW) && yy > 0 && yy < this.world.getHeightBlocks()) {
-            if (this.world.isAirBlock(xx, yy, zz) && this.world.getBlockMaterial(xx, yy - 1, zz).blocksMotion()) {
+            if (this.world.isAirBlock(xx, yy, zz)
+                    && this.world.getBlockMaterial(xx, yy - 1, zz).blocksMotion()
+                    && this.world.getBlockMaterial(xx, yy - 1, zz) != Materials.ICE) {
                 this.world.setBlockWithNotify(xx, yy, zz, Blocks.LAYER_SNOW.id());
             }
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureBoulderMagma.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureBoulderMagma.java
index 8ce53846e..9fa9c0a00 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureBoulderMagma.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureBoulderMagma.java
@@ -42,12 +42,14 @@ public class WorldFeatureBoulderMagma implements WorldFeatureInterface {
                         circlePos.set(x, y, z);
                         if (!world.isAirBlock(circlePos)) {
                             if (random.nextInt(8) == 0) {
-                                world.setBlockType(circlePos, Blocks.COBBLE_BASALT);
+                                world.setBlockType(circlePos, Blocks.ORE_NETHERCOAL_NETHERRACK);
                             }
                         }
                     }
                 }
             }
+
+            world.setBlockType(queryPos.set(pos.x(), pos.y() + 1, pos.z()), Blocks.BLOCK_NETHER_COAL);
         }
 
         return true;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherPatch.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherPatch.java
deleted file mode 100644
index 96be52cc4..000000000
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherPatch.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package net.minecraft.core.world.generate.feature;
-
-import net.minecraft.core.block.Block;
-import net.minecraft.core.world.World;
-import net.minecraft.core.world.pos.TilePos;
-import net.minecraft.core.world.pos.TilePosc;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Random;
-
-public class WorldFeatureNetherPatch implements WorldFeatureInterface {
-    protected final Block<?> defaultBlock;
-    protected final int attempts;
-
-    public WorldFeatureNetherPatch(Block<?> defaultBlock, int attempts) {
-        this.defaultBlock = defaultBlock;
-        this.attempts = attempts;
-    }
-
-    public WorldFeatureNetherPatch(Block<?> defaultBlock) {
-        this(defaultBlock, 64);
-    }
-
-    @Override
-    public boolean place(@NotNull World world, @NotNull Random random, @NotNull TilePosc tilePos) {
-        TilePos pos = new TilePos(tilePos);
-
-        while (world.isAirBlock(pos) && pos.y() > 0) {
-            pos.down();
-        }
-
-        TilePos queryPos = new TilePos();
-
-        for (int i = 0; i < this.attempts; i++) {
-            queryPos.set(
-                pos.x() + random.nextInt(4) - random.nextInt(4),
-                pos.y() + random.nextInt(4) - random.nextInt(4),
-                pos.z() + random.nextInt(4) - random.nextInt(4)
-            );
-
-            if (world.isAirBlock(queryPos)) {
-                Block<?> blockToPlace = this.getBlockToPlace(world, queryPos);
-
-                if (blockToPlace != null && blockToPlace.canStay(world, queryPos)) {
-                    world.setBlockType(queryPos, blockToPlace);
-                }
-            }
-        }
-
-        return true;
-    }
-
-    protected Block<?> getBlockToPlace(World world, TilePos queryPos) {
-        return this.defaultBlock;
-    }
-}
\ No newline at end of file
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherPatchBelow.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherPatchBelow.java
deleted file mode 100644
index 1181b6583..000000000
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherPatchBelow.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package net.minecraft.core.world.generate.feature;
-
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
-import net.minecraft.core.world.World;
-import net.minecraft.core.world.pos.TilePos;
-import net.minecraft.core.world.pos.TilePosc;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Random;
-
-public class WorldFeatureNetherPatchBelow implements WorldFeatureInterface {
-	private final int blockId;
-
-	@MethodParametersAnnotation(names = {"blockId"})
-	public WorldFeatureNetherPatchBelow(int blockId) {
-		this.blockId = blockId;
-	}
-
-	@Override
-	public boolean place(@NotNull World world, @NotNull Random random, @NotNull TilePosc tilePos) {
-		TilePos pos = new TilePos(tilePos);
-
-		while (world.isAirBlock(pos) && pos.y() > 0) {
-			pos.down();
-		}
-
-		TilePos queryPos = new TilePos();
-		TilePos targetPos = new TilePos();
-		TilePos tempPos = new TilePos();
-		Block<?> block = Blocks.blocksList[this.blockId];
-
-		for (int i = 0; i < 8; ++i) {
-			queryPos.set(
-				pos.x() + random.nextInt(4) - random.nextInt(4),
-				pos.y() + random.nextInt(4) - random.nextInt(4),
-				pos.z() + random.nextInt(4) - random.nextInt(4)
-			);
-
-			targetPos.set(queryPos.x(), queryPos.y() - 1, queryPos.z());
-
-			if (world.isAirBlock(queryPos) && world.getBlockType(targetPos) == Blocks.BLOCK_ASH) {
-
-				boolean surroundedByAsh =
-					world.getBlockType(tempPos.set(targetPos).east()) == Blocks.BLOCK_ASH &&
-						world.getBlockType(tempPos.set(targetPos).west()) == Blocks.BLOCK_ASH &&
-						world.getBlockType(tempPos.set(targetPos).south()) == Blocks.BLOCK_ASH &&
-						world.getBlockType(tempPos.set(targetPos).north()) == Blocks.BLOCK_ASH;
-
-				if (surroundedByAsh && block.canStay(world, queryPos)) {
-					world.setBlockType(targetPos, block);
-					world.setBlockType(queryPos, Blocks.AIR);
-				}
-			}
-		}
-
-		return true;
-	}
-}
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatter.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatter.java
index fe0c402e1..7a21f1484 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatter.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatter.java
@@ -12,137 +12,42 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Random;
 
-public class WorldFeatureNetherScatter implements WorldFeatureInterface {
-    private static final int MAX_DOWN_SCAN = 96;
-    private static final int BONE_PILE_ON_ASH_RARE_ONE_IN = 8;
-    private static final int EMBER_FIRST_ROLL_SIDES = 4;
-    private static final int EMBER_FIRST_ROLL_THRESHOLD = 1;
+public abstract class WorldFeatureNetherScatter implements WorldFeatureInterface {
+    protected static final int MAX_DOWN_SCAN = 96;
 
-    private final TilePos scratchGround = new TilePos();
-    private final TilePos scratchPlace = new TilePos();
-    private final TilePos scratchProbe = new TilePos();
-    private final TilePos scratchNeighbor = new TilePos();
-
-    @Override
-    public boolean place(@NotNull World world, @NotNull Random random, @NotNull TilePosc tilePos) {
-        if (random.nextInt(EMBER_FIRST_ROLL_SIDES) >= EMBER_FIRST_ROLL_THRESHOLD) {
-            final Biome seedBiome = world.getBlockBiome(tilePos);
-            if (isOldWorldBiome(seedBiome)) {
-                if (this.tryPlaceEmberReplacingAsh(world, tilePos)) {
-                    return true;
-                }
-            }
-        }
+    protected final @NotNull TilePos scratchGround = new TilePos();
+    protected final @NotNull TilePos scratchPlace = new TilePos();
+    protected static boolean isRubyglassScatterForbiddenSurface(final @NotNull Block<?> surface) {
+        return surface == Blocks.RUBYGLASS_NODE
+            || surface == Blocks.RUBYGLASS_COLUMN
+            || surface == Blocks.RUBYGLASS_GROWTH;
+    }
 
-        final TilePos ground = this.scratchGround.set(tilePos.x(), tilePos.y(), tilePos.z());
+    protected boolean resolveSurfaceScatterSite(final @NotNull World world, final @NotNull TilePosc start) {
+        this.scratchGround.set(start.x(), start.y(), start.z());
         int scanned = 0;
-        while (world.isAirBlock(ground) && ground.y() > 0 && scanned < MAX_DOWN_SCAN) {
-            ground.down();
+        while (world.isAirBlock(this.scratchGround) && this.scratchGround.y() > 0 && scanned < MAX_DOWN_SCAN) {
+            this.scratchGround.down();
             scanned++;
         }
-        if (ground.y() <= 0) { return false; }
-
-        final Block<?> surface = world.getBlockType(ground);
-
-        if (isRubyglassScatterForbiddenSurface(surface)) {
+        if (this.scratchGround.y() <= 0) {
             return false;
         }
-
-        final TilePos placePos = this.scratchPlace.set(ground.x(), ground.y() + 1, ground.z());
-        if (!world.isAirBlock(placePos)) { return false; }
-
-        final Block<?> chosen = pickDecoration(world, random, placePos, surface);
-
-        if (chosen == Blocks.BOULDER_MAGMATIC && surface != Blocks.COBBLE_NETHERRACK && surface != Blocks.NETHERRACK) {
+        final Block<?> surface = world.getBlockType(this.scratchGround);
+        if (isRubyglassScatterForbiddenSurface(surface)) {
             return false;
         }
-        if (chosen == Blocks.BOULDER_SULFURIC && surface != Blocks.BRIMSAND && surface != Blocks.BRIMSTONE && surface != Blocks.BRIMTHAW) {
+        this.scratchPlace.set(this.scratchGround.x(), this.scratchGround.y() + 1, this.scratchGround.z());
+        return world.isAirBlock(this.scratchPlace);
+    }
+
+    protected boolean placeIfCanStay(final @NotNull World world, final @NotNull Block<?> chosen, final @NotNull TilePos placePos) {
+        if (!chosen.canStay(world, placePos)) {
             return false;
         }
-        if (chosen == Blocks.BONE_PILE && isAshSurface(surface)) {
-            if (random.nextInt(BONE_PILE_ON_ASH_RARE_ONE_IN) != 0) {
-                return false;
-            }
-        }
-        if (!chosen.canStay(world, placePos)) { return false; }
-
         world.setBlockType(placePos, chosen);
         return true;
     }
 
-    private static boolean isOldWorldBiome(final @Nullable Biome biome) {
-        return biome == Biomes.NETHER_OLD_WORLD || biome == Biomes.NETHER_OLD_WORLD_DESERT;
-    }
-
-    private static boolean isAshSurface(final @NotNull Block<?> surface) {
-        return surface == Blocks.BLOCK_ASH || surface == Blocks.LAYER_ASH;
-    }
-
-    private static boolean isRubyglassScatterForbiddenSurface(final @NotNull Block<?> surface) {
-        return surface == Blocks.RUBYGLASS_NODE
-                || surface == Blocks.RUBYGLASS_COLUMN
-                || surface == Blocks.RUBYGLASS_GROWTH;
-    }
-
-    private boolean tryPlaceEmberReplacingAsh(final @NotNull World world, final @NotNull TilePosc start) {
-        final int x = start.x();
-        final int z = start.z();
-        final TilePos probe = this.scratchProbe;
-
-        int scanned = 0;
-        for (int y = start.y(); y > 0 && scanned < MAX_DOWN_SCAN; y--, scanned++) {
-            probe.set(x, y, z);
-
-            if (world.getBlockType(probe) != Blocks.BLOCK_ASH) {
-                continue;
-            }
-
-            final TilePos above = this.scratchPlace.set(x, y + 1, z);
-            if (!world.isAirBlock(above)) {
-                continue;
-            }
-
-            if (!isOldWorldBiome(world.getBlockBiome(probe))) {
-                continue;
-            }
-
-            if (!this.isAshSurroundedByAsh(world, x, y, z)) {
-                continue;
-            }
-
-            world.setBlockType(probe, Blocks.EMBER);
-            if (Blocks.LAYER_ASH.canPlaceAt(world, above)) {
-                world.setBlockType(above, Blocks.LAYER_ASH);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    private boolean isAshSurroundedByAsh(final @NotNull World world, final int ax, final int ay, final int az) {
-        final TilePos n = this.scratchNeighbor;
-        return world.getBlockType(n.set(ax + 1, ay, az)) == Blocks.BLOCK_ASH
-                && world.getBlockType(n.set(ax - 1, ay, az)) == Blocks.BLOCK_ASH
-                && world.getBlockType(n.set(ax, ay, az + 1)) == Blocks.BLOCK_ASH
-                && world.getBlockType(n.set(ax, ay, az - 1)) == Blocks.BLOCK_ASH;
-    }
-
-    private @NotNull Block<?> pickDecoration(final @NotNull World world, final @NotNull Random random,
-                                             final @NotNull TilePos placePos, final @NotNull Block<?> surface) {
-        if (surface == Blocks.OBSIDIAN) {
-            return Blocks.BONE_PILE;
-        }
-
-        final Biome biome = world.getBlockBiome(placePos);
-        if (biome == Biomes.NETHER_SULFUR_POOLS) {
-            return random.nextBoolean() ? Blocks.BONE_PILE : Blocks.BOULDER_SULFURIC;
-        }
-        if (biome == Biomes.NETHER_VOLCANIC_ISLANDS || biome == Biomes.NETHER_CRAG
-                || biome == Biomes.NETHER_CRYSTAL_PLAINS || biome == Biomes.NETHER_CRYSTAL_FOREST
-                || biome == Biomes.NETHER_SHELF) {
-            return random.nextBoolean() ? Blocks.BONE_PILE : Blocks.BOULDER_MAGMATIC;
-        }
-
-        return Blocks.BONE_PILE;
-    }
-}
\ No newline at end of file
+    public abstract boolean place(final @NotNull World world, final @NotNull Random random, final @NotNull TilePosc tilePos);
+}
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterBonePile.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterBonePile.java
new file mode 100644
index 000000000..09a03abe6
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterBonePile.java
@@ -0,0 +1,29 @@
+package net.minecraft.core.world.generate.feature;
+
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.pos.TilePosc;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Random;
+
+public final class WorldFeatureNetherScatterBonePile extends WorldFeatureNetherScatter {
+    private static final int BONE_PILE_ON_ASH_ONE_IN = 8;
+
+    private static boolean isAshSurface(final @NotNull Block<?> surface) {
+        return surface == Blocks.BLOCK_ASH || surface == Blocks.LAYER_ASH;
+    }
+
+    @Override
+    public boolean place(final @NotNull World world, final @NotNull Random random, final @NotNull TilePosc tilePos) {
+        if (!this.resolveSurfaceScatterSite(world, tilePos)) {
+            return false;
+        }
+        final Block<?> surface = world.getBlockType(this.scratchGround);
+        if (isAshSurface(surface) && random.nextInt(BONE_PILE_ON_ASH_ONE_IN) != 0) {
+            return false;
+        }
+        return this.placeIfCanStay(world, Blocks.BONE_PILE, this.scratchPlace);
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterBoulderMagmatic.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterBoulderMagmatic.java
new file mode 100644
index 000000000..e8a390ee7
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterBoulderMagmatic.java
@@ -0,0 +1,22 @@
+package net.minecraft.core.world.generate.feature;
+
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.biome.Biome;
+import net.minecraft.core.world.pos.TilePosc;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Random;
+
+public final class WorldFeatureNetherScatterBoulderMagmatic extends WorldFeatureNetherScatter {
+
+    @Override
+    public boolean place(final @NotNull World world, final @NotNull Random random, final @NotNull TilePosc tilePos) {
+        if (!this.resolveSurfaceScatterSite(world, tilePos)) {
+            return false;
+        }
+        return this.placeIfCanStay(world, Blocks.BOULDER_MAGMATIC, this.scratchPlace);
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterBoulderSulfuric.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterBoulderSulfuric.java
new file mode 100644
index 000000000..f23054f9f
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterBoulderSulfuric.java
@@ -0,0 +1,26 @@
+package net.minecraft.core.world.generate.feature;
+
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.biome.Biome;
+import net.minecraft.core.world.biome.Biomes;
+import net.minecraft.core.world.pos.TilePosc;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Random;
+
+public final class WorldFeatureNetherScatterBoulderSulfuric extends WorldFeatureNetherScatter {
+    @Override
+    public boolean place(final @NotNull World world, final @NotNull Random random, final @NotNull TilePosc tilePos) {
+        if (!this.resolveSurfaceScatterSite(world, tilePos)) {
+            return false;
+        }
+        final Block<?> surface = world.getBlockType(this.scratchGround);
+        if (surface != Blocks.BRIMSAND && surface != Blocks.BRIMSTONE && surface != Blocks.BRIMTHAW) {
+            return false;
+        }
+        return this.placeIfCanStay(world, Blocks.BOULDER_SULFURIC, this.scratchPlace);
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterEmberAsh.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterEmberAsh.java
new file mode 100644
index 000000000..aa2c32080
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureNetherScatterEmberAsh.java
@@ -0,0 +1,74 @@
+package net.minecraft.core.world.generate.feature;
+
+import net.minecraft.core.block.Blocks;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.biome.Biome;
+import net.minecraft.core.world.biome.Biomes;
+import net.minecraft.core.world.pos.TilePos;
+import net.minecraft.core.world.pos.TilePosc;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Random;
+
+public final class WorldFeatureNetherScatterEmberAsh extends WorldFeatureNetherScatter {
+    private static final int EMBER_FIRST_ROLL_SIDES = 4;
+    private static final int EMBER_FIRST_ROLL_THRESHOLD = 1;
+
+    private final @NotNull TilePos scratchEmberProbe = new TilePos();
+    private final @NotNull TilePos scratchEmberAbove = new TilePos();
+    private final @NotNull TilePos scratchEmberNeighbor = new TilePos();
+
+    @Override
+    public boolean place(final @NotNull World world, final @NotNull Random random, final @NotNull TilePosc tilePos) {
+        if (random.nextInt(EMBER_FIRST_ROLL_SIDES) < EMBER_FIRST_ROLL_THRESHOLD) {
+            return false;
+        }
+        return this.tryEmberAsh(world, tilePos);
+    }
+
+    private boolean tryEmberAsh(final @NotNull World world, final @NotNull TilePosc start) {
+        final int x = start.x();
+        final int z = start.z();
+
+        int scanned = 0;
+        for (int y = start.y(); y > 0 && scanned < MAX_DOWN_SCAN; y--, scanned++) {
+            this.scratchEmberProbe.set(x, y, z);
+
+            if (world.getBlockType(this.scratchEmberProbe) != Blocks.BLOCK_ASH) {
+                continue;
+            }
+
+            this.scratchEmberAbove.set(x, y + 1, z);
+            if (!world.isAirBlock(this.scratchEmberAbove)) {
+                continue;
+            }
+
+            if (!isOldWorldBiome(world.getBlockBiome(this.scratchEmberProbe))) {
+                continue;
+            }
+
+            if (!isAshSurroundedByAsh(world, x, y, z)) {
+                continue;
+            }
+
+            world.setBlockType(this.scratchEmberProbe, Blocks.EMBER);
+            if (Blocks.LAYER_ASH.canPlaceAt(world, this.scratchEmberAbove)) {
+                world.setBlockType(this.scratchEmberAbove, Blocks.LAYER_ASH);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean isOldWorldBiome(final @Nullable Biome biome) {
+        return biome == Biomes.NETHER_OLD_WORLD || biome == Biomes.NETHER_OLD_WORLD_DESERT;
+    }
+
+    private boolean isAshSurroundedByAsh(final @NotNull World world, final int ax, final int ay, final int az) {
+        return world.getBlockType(this.scratchEmberNeighbor.set(ax + 1, ay, az)) == Blocks.BLOCK_ASH
+            && world.getBlockType(this.scratchEmberNeighbor.set(ax - 1, ay, az)) == Blocks.BLOCK_ASH
+            && world.getBlockType(this.scratchEmberNeighbor.set(ax, ay, az + 1)) == Blocks.BLOCK_ASH
+            && world.getBlockType(this.scratchEmberNeighbor.set(ax, ay, az - 1)) == Blocks.BLOCK_ASH;
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSoulCatcherPatch.java b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSoulCatcherPatch.java
index 4d9ab4857..17ec548f7 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSoulCatcherPatch.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/feature/WorldFeatureSoulCatcherPatch.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.world.generate.feature;
 
+import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.pos.TilePos;
@@ -38,7 +39,12 @@ public class WorldFeatureSoulCatcherPatch implements WorldFeatureInterface {
             if (!world.isAirBlock(this.scratchQuery)) { continue; }
 
             this.scratchBelow.set(qx, qy - 1, qz);
-            final boolean overSoulSand = world.getBlockType(this.scratchBelow) == Blocks.SOULSAND;
+            Block<?> surface = world.getBlockType(this.scratchBelow);
+            final boolean overSoulSand = surface == Blocks.SOULSAND;
+
+            if (surface.equals(Blocks.OBSIDIAN)) {
+                continue;
+            }
 
             if (!overSoulSand && random.nextInt(SPORADIC_CHANCE_DENOM) != 0) {
                 continue;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/ISaveFormat.java b/game/core/src/main/java/net/minecraft/core/world/save/ISaveFormat.java
index 2e34508b0..e0c043e4e 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/ISaveFormat.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/ISaveFormat.java
@@ -3,6 +3,7 @@ package net.minecraft.core.world.save;
 import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.core.world.Dimension;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.io.File;
 import java.util.List;
@@ -18,6 +19,14 @@ public interface ISaveFormat
      */
     String getFormatName();
 
+    /**
+     * Optional conversion subtitle text shown during world conversion.
+     * @return Message to show, or null to use default text.
+     */
+    default @Nullable String getFormatMessage() {
+        return null;
+    }
+
     /**
      * Returns the version associated with the save format.
      * @return The version associated with the save format.
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/SaveConverters.java b/game/core/src/main/java/net/minecraft/core/world/save/SaveConverters.java
index 5e483f259..63fa84e98 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/SaveConverters.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/SaveConverters.java
@@ -3,6 +3,7 @@ package net.minecraft.core.world.save;
 import net.minecraft.core.world.save.conversion.SaveConverter19132To19133;
 import net.minecraft.core.world.save.conversion.SaveConverter19133To19134;
 import net.minecraft.core.world.save.conversion.SaveConverter19134To19135;
+import net.minecraft.core.world.save.conversion.SaveConverter19135To19136;
 import net.minecraft.core.world.save.conversion.SaveConverterLegacyTo19132;
 
 import java.util.ArrayList;
@@ -20,5 +21,6 @@ public class SaveConverters
         saveConverters.add(new SaveConverter19132To19133());
         saveConverters.add(new SaveConverter19133To19134());
         saveConverters.add(new SaveConverter19134To19135());
+        saveConverters.add(new SaveConverter19135To19136());
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java b/game/core/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java
index 7660a31f3..814486e28 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java
@@ -9,6 +9,7 @@ import com.mojang.nbt.tags.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.Dimension;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 
 import java.io.File;
@@ -33,6 +34,11 @@ public abstract class SaveFormatBase
         this.savesDir = savesDir;
     }
 
+    @Override
+    public @Nullable String getFormatMessage() {
+        return null;
+    }
+
     @Override
     public LevelData getLevelData(String worldDirName)
     {
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/SaveFormats.java b/game/core/src/main/java/net/minecraft/core/world/save/SaveFormats.java
index 4abda32e3..30474c051 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/SaveFormats.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/SaveFormats.java
@@ -8,11 +8,10 @@ import net.minecraft.core.world.save.mcregion.SaveFormat19132;
 import net.minecraft.core.world.save.mcregion.SaveFormat19133;
 import net.minecraft.core.world.save.mcregion.SaveFormat19134;
 import net.minecraft.core.world.save.mcregion.SaveFormat19135;
+import net.minecraft.core.world.save.mcregion.SaveFormat19136;
 import org.slf4j.Logger;
 
 import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
 
 public class SaveFormats
 {
@@ -37,5 +36,6 @@ public class SaveFormats
         saveFormats.put(19133, SaveFormat19133.class);
         saveFormats.put(19134, SaveFormat19134.class);
         saveFormats.put(19135, SaveFormat19135.class);
+        saveFormats.put(19136, SaveFormat19136.class);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/conversion/ItemConverters.java b/game/core/src/main/java/net/minecraft/core/world/save/conversion/ItemConverters.java
index b419ad579..6e18cf452 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/conversion/ItemConverters.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/conversion/ItemConverters.java
@@ -1,14 +1,17 @@
 package net.minecraft.core.world.save.conversion;
 
 import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
+import com.mojang.nbt.tags.Tag;
 import net.minecraft.core.item.ItemBucket;
 import net.minecraft.core.util.collection.NamespaceID;
+import org.jetbrains.annotations.NotNull;
 
 public class ItemConverters {
     /**
      * Migrates legacy bucket IDs to the new NBT-based Bucket system.
      */
-    public static void legacyBucketConverter(CompoundTag tag) {
+    public static void legacyBucketConverter(@NotNull CompoundTag tag) {
         short id = tag.getShort("id");
         NamespaceID newState = null;
 
@@ -41,4 +44,29 @@ public class ItemConverters {
             tag.putCompound("Data", dataTag);
         }
     }
-}
\ No newline at end of file
+
+    /**
+     * Recursively migrates legacy bucket item ids in any nested NBT tag tree.
+     */
+    public static void legacyBucketConverterRecursive(CompoundTag tag) {
+        legacyBucketConverter(tag);
+
+        for (final Tag<?> childTag : tag.getValues()) {
+            if (childTag instanceof CompoundTag childCompound) {
+                legacyBucketConverterRecursive(childCompound);
+            } else if (childTag instanceof ListTag childList) {
+                legacyBucketConverterRecursive(childList);
+            }
+        }
+    }
+
+    private static void legacyBucketConverterRecursive(@NotNull ListTag listTag) {
+        for (final Tag<?> listEntry : listTag) {
+            if (listEntry instanceof CompoundTag childCompound) {
+                legacyBucketConverterRecursive(childCompound);
+            } else if (listEntry instanceof ListTag childList) {
+                legacyBucketConverterRecursive(childList);
+            }
+        }
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19134To19135.java b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19134To19135.java
index 6ef88d731..6cc279245 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19134To19135.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19134To19135.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Random;
 
+//Legacy Nether Conversion (8.0)
 public class SaveConverter19134To19135 extends SaveConverterMCRegionBase{
     private static final Logger LOGGER = LogUtils.getLogger();
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19135To19136.java b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19135To19136.java
new file mode 100644
index 000000000..a4b00e865
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19135To19136.java
@@ -0,0 +1,136 @@
+package net.minecraft.core.world.save.conversion;
+
+import com.mojang.logging.LogUtils;
+import com.mojang.nbt.NbtIo;
+import com.mojang.nbt.tags.CompoundTag;
+import com.mojang.nbt.tags.ListTag;
+import com.mojang.nbt.tags.Tag;
+import net.minecraft.core.world.Dimension;
+import net.minecraft.core.world.ProgressListener;
+import net.minecraft.core.world.save.mcregion.RegionFile;
+import net.minecraft.core.world.save.mcregion.RegionFileCache;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+
+
+//Legacy Bucket Conversion (8.0)
+public class SaveConverter19135To19136 extends SaveConverterMCRegionBase {
+    private static final Logger LOGGER = LogUtils.getLogger();
+
+    @Override
+    public int fromVersion() {
+        return 19135;
+    }
+
+    @Override
+    public int toVersion() {
+        return 19136;
+    }
+
+    @Override
+    public void convertSave(@NotNull CompoundTag levelData, @NotNull File savesDir, @NotNull String worldDirName, @NotNull ProgressListener progress) {
+        convertBasketTileEntities(levelData);
+        ItemConverters.legacyBucketConverterRecursive(levelData);
+        convertPlayerDataFiles(savesDir, worldDirName);
+        super.convertSave(levelData, savesDir, worldDirName, progress);
+    }
+
+    @Override
+    int convertDimensionRegions(@NotNull Dimension dimension, @NotNull ArrayList<File> regionFiles, int conversionsPerformed, int totalConversions, @NotNull ProgressListener progress) {
+        Collections.sort(regionFiles);
+        int progressValue = 0;
+        int conversions = 0;
+
+        for (File region : regionFiles) {
+            progress.progressStagePercentage(progressValue);
+
+            RegionFile regionFile = new RegionFile(region);
+
+            for (int x = 0; x < 32; x++) {
+                for (int z = 0; z < 32; z++) {
+                    try {
+                        DataInputStream inputStream = regionFile.getChunkDataInputStream(x, z);
+                        if (inputStream == null) continue;
+                        DataOutputStream outputStream = regionFile.getChunkDataOutputStream(x, z);
+                        CompoundTag chunkData = NbtIo.read(inputStream);
+
+                        convertBasketTileEntities(chunkData);
+                        ItemConverters.legacyBucketConverterRecursive(chunkData);
+                        NbtIo.write(chunkData, outputStream);
+
+                        inputStream.close();
+                        outputStream.close();
+                    } catch (IOException e) {
+                        LOGGER.error("Failed to convert chunk X:{}, Z:{}, in region {}!", x, z, region.toPath(), e);
+                    }
+                }
+            }
+
+            conversions++;
+            progressValue = (int) Math.round((100D * (double) (conversionsPerformed + conversions)) / (double) totalConversions);
+        }
+
+        RegionFileCache.flushCache();
+
+        return conversions;
+    }
+
+    private static void convertBasketTileEntities(@NotNull CompoundTag rootTag) {
+        CompoundTag levelTag = rootTag.getCompoundOrDefault("Level", null);
+        if (levelTag == null) {
+            return;
+        }
+
+        ListTag tileEntities = levelTag.getListOrDefault("TileEntities", null);
+        if (tileEntities == null) {
+            return;
+        }
+
+        for (Tag<?> tag : tileEntities) {
+            if (!(tag instanceof CompoundTag tileEntityTag)) {
+                continue;
+            }
+            String id = tileEntityTag.getString("id");
+            if (!"minecraft:basket".equals(id) && !"Basket".equals(id)) {
+                continue;
+            }
+
+            ListTag itemsTag = tileEntityTag.getListOrDefault("Items", null);
+            if (itemsTag == null) {
+                continue;
+            }
+
+            for (Tag<?> itemTag : itemsTag) {
+                if (itemTag instanceof CompoundTag itemCompound) {
+                    ItemConverters.legacyBucketConverter(itemCompound);
+                }
+            }
+        }
+    }
+
+    private void convertPlayerDataFiles(@NotNull File savesDir, @NotNull String worldDirName) {
+        File playersDir = new File(new File(savesDir, worldDirName), "players");
+        File[] playerFiles = playersDir.listFiles((dir, name) -> name.endsWith(".dat"));
+        if (playerFiles == null) {
+            return;
+        }
+
+        for (File playerFile : playerFiles) {
+            try {
+                CompoundTag playerData = NbtIo.readCompressed(Files.newInputStream(playerFile.toPath()));
+                ItemConverters.legacyBucketConverterRecursive(playerData);
+                NbtIo.writeCompressed(playerData, Files.newOutputStream(playerFile.toPath()));
+            } catch (IOException e) {
+                LOGGER.error("Failed to convert player data file '{}' for world '{}'!", playerFile.getName(), worldDirName, e);
+            }
+        }
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/mcregion/SaveFormat19135.java b/game/core/src/main/java/net/minecraft/core/world/save/mcregion/SaveFormat19135.java
index 9ded2b877..7421fa599 100644
--- a/game/core/src/main/java/net/minecraft/core/world/save/mcregion/SaveFormat19135.java
+++ b/game/core/src/main/java/net/minecraft/core/world/save/mcregion/SaveFormat19135.java
@@ -15,6 +15,9 @@ public class SaveFormat19135 extends SaveFormatBase {
         return "BTARegion";
     }
 
+    @Override
+    public String getFormatMessage(){ return "Converting Legacy Nether...";}
+
     @Override
     public int getSaveVersion() {
         return 19135;
diff --git a/game/core/src/main/java/net/minecraft/core/world/save/mcregion/SaveFormat19136.java b/game/core/src/main/java/net/minecraft/core/world/save/mcregion/SaveFormat19136.java
new file mode 100644
index 000000000..cc9dd93fb
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/world/save/mcregion/SaveFormat19136.java
@@ -0,0 +1,39 @@
+package net.minecraft.core.world.save.mcregion;
+
+import net.minecraft.core.world.Dimension;
+import net.minecraft.core.world.save.SaveFormatBase;
+
+import java.io.File;
+
+public class SaveFormat19136 extends SaveFormatBase {
+    public SaveFormat19136(File savesDir) {
+        super(savesDir);
+    }
+
+    @Override
+    public String getFormatName() {
+        return "BTARegion";
+    }
+
+    @Override
+    public String getFormatMessage(){ return "Converting Legacy Buckets...";}
+
+    @Override
+    public int getSaveVersion() {
+        return 19136;
+    }
+
+    @Override
+    public void flushCache() {
+        RegionFileCache.flushCache();
+    }
+
+    @Override
+    public File getDimensionRootDir(String worldDirName, Dimension dimension) {
+        File worldDir = new File(savesDir, worldDirName);
+
+        File worldDimsDir = new File(worldDir, "dimensions");
+
+        return new File(worldDimsDir, Integer.toString(dimension.id));
+    }
+}
diff --git a/game/core/src/main/resources/assets/minecraft/lang/en_US/gui.lang b/game/core/src/main/resources/assets/minecraft/lang/en_US/gui.lang
index a2406e4fa..f7521cce3 100644
--- a/game/core/src/main/resources/assets/minecraft/lang/en_US/gui.lang
+++ b/game/core/src/main/resources/assets/minecraft/lang/en_US/gui.lang
@@ -308,6 +308,10 @@ gui.options.hudeditor.onboarding.reset=Press '%1$s' to reset layout to default
 gui.options.hudeditor.onboarding.exit=Press '%1$s' to leave the HUD Editor
 gui.options.hudeditor.onboarding.reopen=Press '%1$s' to see this screen again!
 gui.options.hudeditor.onboarding.begin=Click anywhere to begin
+gui.options.hudeditor.snap_to_fill=Snap To Fill
+gui.options.hudeditor.scale=GUI Scale
+gui.options.hudeditor.chat_width=Chat Width
+gui.options.hudeditor.chat_height=Chat Height
 
 gui.sound_test.label.title=Sound Test
 gui.sound_test.label.repo=Sound Repository: %s
diff --git a/game/core/src/main/resources/assets/minecraft/lang/en_US/item.lang b/game/core/src/main/resources/assets/minecraft/lang/en_US/item.lang
index fe9875735..684c26c67 100644
--- a/game/core/src/main/resources/assets/minecraft/lang/en_US/item.lang
+++ b/game/core/src/main/resources/assets/minecraft/lang/en_US/item.lang
@@ -6,8 +6,8 @@ item.tool.pickaxe.iron.name=Iron Pickaxe
 item.tool.pickaxe.iron.desc=Pick some stone with this iron tool.
 item.tool.axe.iron.name=Iron Axe
 item.tool.axe.iron.desc=Chop some trees with this iron tool.
-item.tool.firestriker.name=Fire Striker
-item.tool.firestriker.desc=Don't even think about it.
+item.tool.firestriker.iron.name=Fire Striker
+item.tool.firestriker.iron.desc=Don't even think about it.
 item.tool.firestriker.steel.name=Steel Fire Striker
 item.tool.firestriker.steel.desc=Even more dangerous.
 item.food.apple.name=Apple
@@ -505,8 +505,8 @@ item.statue.pigman.desc=An ancient marble statue found in a long-forgotten place
 item.dough.name=Dough
 item.dough.desc=Uncooked dough. Can be baked into bread.
 
-item.rubyglass.name=Rubyglass
-item.rubyglass.desc=A shard of charged rubyglass, brimming with energy.
+item.rubyglass.crystal.name=Rubyglass
+item.rubyglass.crystal.desc=A shard of charged rubyglass, brimming with energy.
 
 item.armor.wolf.leather.name=Leather Wolf Armor
 item.armor.wolf.leather.desc=Keep your best friend safe with this soft leather shell.
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 cc2ed3fb2..bf8544bbf 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
@@ -42,11 +42,14 @@ options.fancyGraphics=Graphics
 options.connectedGlass=Connected Glass
 options.graphics.fancy=Fancy
 options.graphics.fast=Fast
-options.guiScale=GUI Scale
+options.guiScale=Global GUI Scale
 options.guiScale.auto=Auto
+options.guiScale.disabled=Disabled
 options.guiScale.small=Small
 options.guiScale.normal=Normal
 options.guiScale.large=Large
+options.guiScaleOverride=GUI Scale Override
+options.guiScaleOverride.disabled=Disabled
 options.advancedOpengl=Advanced OpenGL
 options.treeShadows=Leaf Shadowing
 options.transparencyDepthCheck=Translucent Depth Check
@@ -324,6 +327,15 @@ options.horizontalLogTextAlignment.left=Left
 options.horizontalLogTextAlignment.center=Center
 options.horizontalLogTextAlignment.right=Right
 
+options.horizontalChatTextAlignment=Horizontal Alignment
+options.horizontalChatTextAlignment.left=Left
+options.horizontalChatTextAlignment.center=Center
+options.horizontalChatTextAlignment.right=Right
+options.horizontalSubtitleTextAlignment=Horizontal Alignment
+options.horizontalSubtitleTextAlignment.left=Left
+options.horizontalSubtitleTextAlignment.center=Center
+options.horizontalSubtitleTextAlignment.right=Right
+
 options.verticalInfoTextAlignment=Vertical Alignment
 options.verticalInfoTextAlignment.top=Top
 options.verticalInfoTextAlignment.center=Center
@@ -334,6 +346,15 @@ options.verticalLogTextAlignment.top=Top
 options.verticalLogTextAlignment.center=Center
 options.verticalLogTextAlignment.bottom=Bottom
 
+options.verticalChatTextAlignment=Vertical Alignment
+options.verticalChatTextAlignment.top=Top
+options.verticalChatTextAlignment.center=Center
+options.verticalChatTextAlignment.bottom=Bottom
+options.verticalSubtitleTextAlignment=Vertical Alignment
+options.verticalSubtitleTextAlignment.top=Top
+options.verticalSubtitleTextAlignment.center=Center
+options.verticalSubtitleTextAlignment.bottom=Bottom
+
 key.attack=Attack
 key.interact=Interact
 key.pickBlock=Pick Block
diff --git a/game/core/src/main/resources/assets/minecraft/lang/en_US/subtitles.lang b/game/core/src/main/resources/assets/minecraft/lang/en_US/subtitles.lang
index a61904b28..a71e37e33 100644
--- a/game/core/src/main/resources/assets/minecraft/lang/en_US/subtitles.lang
+++ b/game/core/src/main/resources/assets/minecraft/lang/en_US/subtitles.lang
@@ -107,6 +107,16 @@ subtitles.tile.dispenser.fire=Dispenser fire
 subtitles.tile.activator.click=Activator click
 subtitles.tile.activator.use=Activator use
 
+subtitles.tile.crystal=Crystal tinkle
+
+subtitles.tile.scrape=Statue scraping
+
+subtitles.tile.deepcrumble=Deep crumble
+subtitles.tile.deepboom=Deep boom
+subtitles.tile.crumble=Crumble
+subtitles.tile.acidbubble=Acid bubble
+subtitles.tile.deepquietboom=Deep quiet boom
+
 subtitles.hurt.flesh=Hurt flesh
 
 subtitles.fire.ignite=Fire lit
diff --git a/game/core/src/main/resources/assets/minecraft/lang/en_US/tile.lang b/game/core/src/main/resources/assets/minecraft/lang/en_US/tile.lang
index 4b50a3e00..a41e92957 100644
--- a/game/core/src/main/resources/assets/minecraft/lang/en_US/tile.lang
+++ b/game/core/src/main/resources/assets/minecraft/lang/en_US/tile.lang
@@ -296,6 +296,8 @@ tile.slab.basalt.carved.name=Polished Basalt Slab
 tile.slab.basalt.carved.desc=A slab of polished basalt.
 tile.slab.permafrost.carved.name=Polished Permafrost Slab
 tile.slab.permafrost.carved.desc=A slab of polished permafrost.
+tile.slab.slate.carved.name=Polished Slate Slab
+tile.slab.slate.carved.desc=A slab of polished slate.
 
 tile.slab.planks.oak.painted.name=Mystery Wooden Slab
 tile.slab.planks.oak.painted.desc=How did you get this?!
@@ -865,14 +867,20 @@ tile.piston.base.name=Piston
 tile.piston.base.desc=Pushes blocks but does not pull them.
 tile.piston.base.sticky.name=Sticky Piston
 tile.piston.base.sticky.desc=Pushes and pulls blocks.
-tile.piston.head.name=Piston Head
-tile.piston.head.desc=The pushy part of the piston.
-tile.piston.moving.name=Piston Mover
-tile.piston.moving.desc=The invisible moving part of the piston.
 tile.piston.base.steel.name=Reinforced Piston
 tile.piston.base.steel.desc=Pushes blocks and entities with immense force.
+tile.piston.base.detached.name=Detached Piston
+tile.piston.base.detached.desc=Emotionally unavailable.
+tile.piston.base.sticky.detached.name=Detached Sticky Piston
+tile.piston.base.sticky.detached.desc=Emotionally unavailable and covered in slime.
+tile.piston.base.steel.detached.name=Detached Reinforced Piston
+tile.piston.base.steel.detached.desc=Emotionally unavailable, but made of steel.
+tile.piston.head.name=Piston Head
+tile.piston.head.desc=The pushy part of the piston.
 tile.piston.head.steel.name=Reinforced Piston Head
 tile.piston.head.steel.desc=The pushy part of the steel piston.
+tile.piston.moving.name=Piston Mover
+tile.piston.moving.desc=The invisible moving part of the piston.
 
 tile.noteblock.name=Note Block
 tile.noteblock.desc=Plays a musical note when powered.
diff --git a/game/core/src/main/resources/assets/minecraft/sounds/sounds.json b/game/core/src/main/resources/assets/minecraft/sounds/sounds.json
index 34fdb5f78..10b3a8b1a 100644
--- a/game/core/src/main/resources/assets/minecraft/sounds/sounds.json
+++ b/game/core/src/main/resources/assets/minecraft/sounds/sounds.json
@@ -929,8 +929,8 @@
       "tile/deepcrumble.ogg"
     ]
   },
-  "random.scrape": {
-    "subtitle": "subtitles.random.scrape",
+  "tile.scrape": {
+    "subtitle": "subtitles.tile.scrape",
     "sounds": [
       "tile/scrape.ogg"
     ]
diff --git a/game/server/src/main/java/net/minecraft/server/MinecraftServer.java b/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
index c073953af..22c248128 100644
--- a/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/game/server/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -31,7 +31,6 @@ import net.minecraft.core.player.gamemode.Gamemodes;
 import net.minecraft.core.util.pool.ObjectPool;
 import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.core.world.pos.TilePos;
-import net.minecraft.core.world.save.mcregion.SaveFormat19135;
 import net.minecraft.core.world.settings.WorldConfiguration;
 import net.minecraft.core.world.type.WorldTypeGroups;
 import net.minecraft.server.entity.player.PlayerServer;
@@ -380,7 +379,11 @@ public class MinecraftServer
             }
         }
         LOGGER.info("Preparing level \"{}\"", lName);
-        initWorld(new SaveFormat19135(new File(".")), lName, randomLong);
+        ISaveFormat activeFormat = SaveFormats.createSaveFormat(CURRENT_SAVE_VERSION, new File("."));
+        if (activeFormat == null) {
+            throw new IllegalStateException("No save format registered for current save version " + CURRENT_SAVE_VERSION);
+        }
+        initWorld(activeFormat, lName, randomLong);
         LOGGER.info("Generating RSA key...");
         try
         {
@@ -467,15 +470,20 @@ public class MinecraftServer
     private void doWorldConversion(int fromVersion, String worldDirName)
     {
         ConvertProgressUpdater updater = new ConvertProgressUpdater();
-        ISaveFormat fromWorldFormat = SaveFormats.createSaveFormat(fromVersion, new File("."));
+        int currentVersion = fromVersion;
 
-        if (fromWorldFormat != null)
+        while (currentVersion < CURRENT_SAVE_VERSION)
         {
-            // Get highest converter
+            ISaveFormat fromWorldFormat = SaveFormats.createSaveFormat(currentVersion, new File("."));
+            if (fromWorldFormat == null)
+            {
+                break;
+            }
+
             ISaveConverter converterToUse = null;
             for (ISaveConverter converter : SaveConverters.saveConverters)
             {
-                if (converter.fromVersion() == fromVersion)
+                if (converter.fromVersion() == currentVersion)
                 {
                     if (converterToUse == null || converter.toVersion() > converterToUse.toVersion())
                     {
@@ -484,21 +492,50 @@ public class MinecraftServer
                 }
             }
 
-            if (converterToUse != null)
+            if (converterToUse == null)
             {
-                ISaveFormat toWorldFormat = SaveFormats.createSaveFormat(converterToUse.toVersion(), new File("."));
+                break;
+            }
+            if (converterToUse.toVersion() <= currentVersion)
+            {
+                LOGGER.warn("World conversion halted for '{}' due to non-advancing converter {} -> {}.", worldDirName, converterToUse.fromVersion(), converterToUse.toVersion());
+                break;
+            }
 
-                if (toWorldFormat != null)
-                {
-                    CompoundTag levelDataTag = toWorldFormat.getLevelDataRaw(worldDirName);
+            ISaveFormat toWorldFormat = SaveFormats.createSaveFormat(converterToUse.toVersion(), new File("."));
+            if (toWorldFormat == null)
+            {
+                break;
+            }
 
-                    converterToUse.convertSave(levelDataTag, new File("."), worldDirName, updater);
+            CompoundTag levelDataTag = toWorldFormat.getLevelDataRaw(worldDirName);
 
-                    levelDataTag.putInt("version", toWorldFormat.getSaveVersion());
+            converterToUse.convertSave(levelDataTag, new File("."), worldDirName, updater);
 
-                    LevelStorage saveHandler = toWorldFormat.getLevelStorage(worldDirName, false);
-                    saveHandler.saveLevelDataRaw(levelDataTag);
-                }
+            levelDataTag.putInt("version", toWorldFormat.getSaveVersion());
+
+            LevelStorage saveHandler = toWorldFormat.getLevelStorage(worldDirName, false);
+            saveHandler.saveLevelDataRaw(levelDataTag);
+
+            CompoundTag reloadedLevelData = toWorldFormat.getLevelDataRaw(worldDirName);
+            int reloadedVersion = reloadedLevelData != null ? reloadedLevelData.getInteger("version") : -1;
+            if (reloadedVersion < toWorldFormat.getSaveVersion())
+            {
+                LOGGER.warn("World conversion write verification failed for '{}' (expected >= {}, got {}).", worldDirName, toWorldFormat.getSaveVersion(), reloadedVersion);
+                break;
+            }
+
+            currentVersion = reloadedVersion;
+        }
+
+        ISaveFormat currentFormat = SaveFormats.createSaveFormat(CURRENT_SAVE_VERSION, new File("."));
+        if (currentFormat != null)
+        {
+            CompoundTag finalLevelData = currentFormat.getLevelDataRaw(worldDirName);
+            if (finalLevelData != null && finalLevelData.getInteger("version") < CURRENT_SAVE_VERSION)
+            {
+                finalLevelData.putInt("version", CURRENT_SAVE_VERSION);
+                currentFormat.getLevelStorage(worldDirName, false).saveLevelDataRaw(finalLevelData);
             }
         }
 
diff --git a/util/datagen/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java b/util/datagen/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java
index 50656deab..ae46c6d71 100644
--- a/util/datagen/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java
+++ b/util/datagen/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java
@@ -67,13 +67,13 @@ class WorkbenchGenerator {
         generateMiscNewRecipes();
 
         RecipeBuilder.Shaped(CORE_NAMESPACE)
-                .setShape(
-                    "CCW",
-                    "PPP")
-                .addInput('C', Items.CLOTH)
-                .addInput('W', "minecraft:wools")
-                .addInput('P', "minecraft:planks")
-                .create("bed", Items.BED.getDefaultStack());
+            .setShape(
+                "CCW",
+                "PPP")
+            .addInput('C', Items.CLOTH)
+            .addInput('W', "minecraft:wools")
+            .addInput('P', "minecraft:planks")
+            .create("bed", Items.BED.getDefaultStack());
 
         RecipeBuilder.Shaped(CORE_NAMESPACE)
             .setShape(
@@ -84,13 +84,13 @@ class WorkbenchGenerator {
             .create("seat", Items.SEAT.getDefaultStack());
 
         RecipeBuilder.Shaped(CORE_NAMESPACE)
-                .setShape(
-                    "###",
-                    "X X",
-                    "XXX")
-                .addInput('#', Items.LEATHER)
-                .addInput('X', Items.WHEAT)
-                .create("basket", Items.BASKET.getDefaultStack());
+            .setShape(
+                "###",
+                "X X",
+                "XXX")
+            .addInput('#', Items.LEATHER)
+            .addInput('X', Items.WHEAT)
+            .create("basket", Items.BASKET.getDefaultStack());
 
         RecipeBuilder.Shaped(CORE_NAMESPACE)
             .setShape(
@@ -1340,7 +1340,7 @@ class WorkbenchGenerator {
             .create("tnt", new ItemStack(Blocks.TNT));
 
         RecipeBuilder.Shapeless(CORE_NAMESPACE).addInput("minecraft:stones").create("stone_button", new ItemStack(Blocks.BUTTON_STONE, 4));
-        RecipeBuilder.Shapeless(CORE_NAMESPACE).addInput(Blocks.PLANKS_OAK).create("wooden_button", new ItemStack(Blocks.BUTTON_PLANKS, 4));
+        RecipeBuilder.Shapeless(CORE_NAMESPACE).addInput(Blocks.PLANKS_OAK).create("wooden_button", new ItemStack(Blocks.BUTTON_PLANKS_OAK, 4));
         for (DyeColor color : DyeColor.values()) {
             RecipeBuilder.Shapeless(CORE_NAMESPACE).addInput(Blocks.PLANKS_OAK_PAINTED, color.blockMeta).create(color.colorID + "_wooden_button", new ItemStack(Blocks.BUTTON_PLANKS_PAINTED, 4, color.blockMeta << 4));
         }
@@ -1517,7 +1517,7 @@ class WorkbenchGenerator {
         Registries.RECIPES.WORKBENCH.register(String.format(format, "lamps"), new RecipeEntryUndyeing(new RecipeSymbol("minecraft:lamps"), new ItemStack(Blocks.LAMP_IDLE)));
         Registries.RECIPES.WORKBENCH.register(String.format(format, "wools"), new RecipeEntryUndyeing(new RecipeSymbol("minecraft:wools"), new ItemStack(Blocks.WOOL)));
         Registries.RECIPES.WORKBENCH.register(String.format(format, "chests"), new RecipeEntryUndyeing(new RecipeSymbol("minecraft:chests"), new ItemStack(Blocks.CHEST_PLANKS_OAK)));
-        Registries.RECIPES.WORKBENCH.register(String.format(format, "buttons_planks"), new RecipeEntryUndyeing(new RecipeSymbol("minecraft:button_planks"), new ItemStack(Blocks.BUTTON_PLANKS)));
+        Registries.RECIPES.WORKBENCH.register(String.format(format, "buttons_planks"), new RecipeEntryUndyeing(new RecipeSymbol("minecraft:button_planks"), new ItemStack(Blocks.BUTTON_PLANKS_OAK)));
         Registries.RECIPES.WORKBENCH.register(String.format(format, "pressureplates_planks"), new RecipeEntryUndyeing(new RecipeSymbol("minecraft:pressureplates_planks"), new ItemStack(Blocks.PRESSURE_PLATE_PLANKS_OAK)));
     }
 
@@ -1540,18 +1540,6 @@ class WorkbenchGenerator {
     }
 
     private static void generateMiscNewRecipes() {
-        // Carved Stones
-        RecipeBuilderShaped templateCarvedStone = RecipeBuilder.Shaped(CORE_NAMESPACE).setShape("SS", "SS");
-        templateCarvedStone.addInput('S', Blocks.STONE_POLISHED).create("carved_stone", new ItemStack(Blocks.STONE_CARVED, 2));
-        templateCarvedStone.addInput('S', Blocks.BASALT_POLISHED).create("carved_basalt", new ItemStack(Blocks.BASALT_CARVED, 2));
-        templateCarvedStone.addInput('S', Blocks.LIMESTONE_POLISHED).create("carved_limestone", new ItemStack(Blocks.LIMESTONE_CARVED, 2));
-        templateCarvedStone.addInput('S', Blocks.GRANITE_POLISHED).create("carved_granite", new ItemStack(Blocks.GRANITE_CARVED, 2));
-        templateCarvedStone.addInput('S', Blocks.PERMAFROST_POLISHED).create("carved_permafrost", new ItemStack(Blocks.PERMAFROST_CARVED, 2));
-        templateCarvedStone.addInput('S', Blocks.MARBLE).create("marble_capstone", new ItemStack(Blocks.CAPSTONE_MARBLE, 2));
-        templateCarvedStone.addInput('S', Blocks.SLATE_POLISHED).create("carved_slate", new ItemStack(Blocks.SLATE_CARVED, 2));
-        templateCarvedStone.addInput('S', Blocks.NETHERRACK_POLISHED).create("carved_netherrack", new ItemStack(Blocks.NETHERRACK_CARVED, 2));
-        templateCarvedStone.addInput('S', Blocks.GLOOMSTONE_POLISHED).create("carved_gloomstone", new ItemStack(Blocks.GLOOMSTONE_CARVED, 2));
-
         // Brimstone Formatting
         RecipeBuilder.Shaped(CORE_NAMESPACE).setShape("SS", "SS").addInput('S', Blocks.BRIMSAND).create("brimstone", new ItemStack(Blocks.BRIMSTONE, 2));
         RecipeBuilder.Shaped(CORE_NAMESPACE).setShape("SSS").addInput('S', Blocks.BRIMSTONE).create("brimstone_slab", new ItemStack(Blocks.SLAB_BRIMSTONE, 6));
@@ -1569,6 +1557,68 @@ class WorkbenchGenerator {
         RecipeBuilder.Shapeless(CORE_NAMESPACE).addInput(Blocks.LOG_SCORCHED).create("scorched_log_to_black_wooden_planks", new ItemStack(Blocks.PLANKS_OAK_PAINTED, 4, 15));
     }
 
+    /**
+     * Unused carved stone recipes
+     */
+    @SuppressWarnings("unused")
+    private static void generateCarvedStoneRecipesDisabled() {
+        RecipeBuilderShaped templateCarvedStone = RecipeBuilder.Shaped(CORE_NAMESPACE)
+            .setShape(
+                "   ",
+                "SSS",
+                "SSS");
+        templateCarvedStone.addInput('S', Blocks.STONE_POLISHED).create("carved_stone", new ItemStack(Blocks.STONE_CARVED, 6));
+        templateCarvedStone.addInput('S', Blocks.BASALT_POLISHED).create("carved_basalt", new ItemStack(Blocks.BASALT_CARVED, 6));
+        templateCarvedStone.addInput('S', Blocks.LIMESTONE_POLISHED).create("carved_limestone", new ItemStack(Blocks.LIMESTONE_CARVED, 6));
+        templateCarvedStone.addInput('S', Blocks.GRANITE_POLISHED).create("carved_granite", new ItemStack(Blocks.GRANITE_CARVED, 6));
+        templateCarvedStone.addInput('S', Blocks.PERMAFROST_POLISHED).create("carved_permafrost", new ItemStack(Blocks.PERMAFROST_CARVED, 6));
+        RecipeBuilder.Shaped(CORE_NAMESPACE).setShape("SS", "SS")
+            .addInput('S', Blocks.MARBLE).create("marble_capstone", new ItemStack(Blocks.CAPSTONE_MARBLE, 2));
+        templateCarvedStone.addInput('S', Blocks.SLATE_POLISHED).create("carved_slate", new ItemStack(Blocks.SLATE_CARVED, 6));
+        templateCarvedStone.addInput('S', Blocks.NETHERRACK_POLISHED).create("carved_netherrack", new ItemStack(Blocks.NETHERRACK_CARVED, 6));
+        templateCarvedStone.addInput('S', Blocks.GLOOMSTONE_POLISHED).create("carved_gloomstone", new ItemStack(Blocks.GLOOMSTONE_CARVED, 6));
+
+        RecipeBuilder.Shaped(CORE_NAMESPACE)
+            .setShape("SSS")
+            .addInput('S', Blocks.STONE_CARVED)
+            .create("stone_carved_to_slab", new ItemStack(Blocks.SLAB_STONE_POLISHED, 6));
+
+        RecipeBuilder.Shaped(CORE_NAMESPACE)
+            .setShape("SSS")
+            .addInput('S', Blocks.BASALT_CARVED)
+            .create("basalt_carved_to_slab", new ItemStack(Blocks.SLAB_BASALT_POLISHED, 6));
+
+        RecipeBuilder.Shaped(CORE_NAMESPACE)
+            .setShape("SSS")
+            .addInput('S', Blocks.LIMESTONE_CARVED)
+            .create("limestone_carved_to_slab", new ItemStack(Blocks.SLAB_LIMESTONE_POLISHED, 6));
+
+        RecipeBuilder.Shaped(CORE_NAMESPACE)
+            .setShape("SSS")
+            .addInput('S', Blocks.GRANITE_CARVED)
+            .create("granite_carved_to_slab", new ItemStack(Blocks.SLAB_GRANITE_POLISHED, 6));
+
+        RecipeBuilder.Shaped(CORE_NAMESPACE)
+            .setShape("SSS")
+            .addInput('S', Blocks.PERMAFROST_CARVED)
+            .create("permafrost_carved_to_slab", new ItemStack(Blocks.SLAB_PERMAFROST_POLISHED, 6));
+
+        RecipeBuilder.Shaped(CORE_NAMESPACE)
+            .setShape("SSS")
+            .addInput('S', Blocks.SLATE_CARVED)
+            .create("slate_carved_to_slab", new ItemStack(Blocks.SLAB_SLATE_POLISHED, 6));
+
+        RecipeBuilder.Shaped(CORE_NAMESPACE)
+            .setShape("SSS")
+            .addInput('S', Blocks.NETHERRACK_CARVED)
+            .create("netherrack_carved_to_slab", new ItemStack(Blocks.SLAB_NETHERRACK_POLISHED, 6));
+
+        RecipeBuilder.Shaped(CORE_NAMESPACE)
+            .setShape("SSS")
+            .addInput('S', Blocks.GLOOMSTONE_CARVED)
+            .create("gloomstone_carved_to_slab", new ItemStack(Blocks.SLAB_GLOOMSTONE_POLISHED, 6));
+    }
+
     private static void generateAcidConversions() {
         // Each pair: { input, output }
         final Block<?>[][] pairs = {
